package com.ray.service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sound.midi.Soundbank;

import org.apache.ibatis.annotations.Case;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSONObject;
import com.google.appengine.repackaged.org.joda.time.DateTime;
import com.ray.bean.ApplyRepairFormBean;
import com.ray.bean.CompanyBean;
import com.ray.bean.CompanyMaterialCountBean;
import com.ray.bean.CompanyMaterialTableBean;
import com.ray.bean.DatatablesViewPageBean;
import com.ray.bean.FeedOrderDetailBean;
import com.ray.bean.FeedOrderMainBean;
import com.ray.bean.FeedUseMaterialCountBean;
import com.ray.bean.FeedingAndReportBean;
import com.ray.bean.FinishStockBean;
import com.ray.bean.MaterialPositionBean;
import com.ray.bean.MergeBean;
import com.ray.bean.OrderBean;
import com.ray.bean.OrderInfoDetailBean;
import com.ray.bean.ProcessBean;
import com.ray.bean.PurchaseOrderBean;
import com.ray.bean.PutOutWarehouseBean;
import com.ray.bean.ReportBean;
import com.ray.bean.UserBean;
import com.ray.bean.WarehouseInOutDetailBean;
import com.ray.bean.WarehouseInSumMoneyBean;
import com.ray.bean.WorkshopProductionCycleBean;
import com.ray.exception.ServiceException;
import com.ray.mapper.ApplyRepairFormMapper;
import com.ray.mapper.ApprovalMapper;
import com.ray.mapper.BasicDataMapper;
import com.ray.mapper.CompanyMapper;
import com.ray.mapper.CompanyMaterialMapper;
import com.ray.mapper.DingTalkMapper;
import com.ray.mapper.FeedUseMaterialCountMapper;
import com.ray.mapper.IssueNoteMapper;
import com.ray.mapper.OrderMapper;
import com.ray.mapper.OtherWarehouseMapper;
import com.ray.mapper.PurchaseOrderMapper;
import com.ray.mapper.WarehouseMapper;
import com.ray.pojo.MyUser;
import com.ray.util.CreateIdUtil;
import com.ray.util.RedirectUrlUtil;
import com.ray.util.RequestUtil;
import com.ray.util.ReturnStringUtil;
import com.ray.util.StringUtil;
import com.sun.mail.mbox.Mailbox;

import net.sf.json.JSONArray;

/**
 * 仓库逻辑层
* <p>Title: WarehouseService</p>  
* <p>Description: </p>  
* @author 李斌  
* @date 2018年9月14日
 */
@Service
public class WarehouseService {
	
	@Autowired
	WarehouseMapper warehouseMapper;
	@Autowired
	PurchaseOrderMapper purchaseOrderMapper;
	@Autowired
	DingTalkMapper dingTalkMapper;
	@Autowired
	CompanyMaterialMapper companyMaterialMapper;
	@Autowired
	OtherWarehouseMapper otherWarehouseMapper;
	@Autowired
	OrderMapper orderMapper;
	@Autowired
	FeedUseMaterialCountMapper feedUseMaterialCountMapper;
	@Autowired
	ApplyRepairFormMapper applyRepairFormMapper;
	@Autowired
	CompanyMapper compangMapper;
	@Autowired
	IssueNoteMapper issueNoteMapper;
	@Autowired
	BasicDataMapper basicDataMapper;
	@Autowired
	ApprovalMapper approvalMapper;
	@Autowired
	ShoppingMallService shoppingMallService;
	
	@Autowired
	CompanyMaterialService companyMaterialService;
	@Autowired
	UserService userService;
	@Autowired
	OrderService orderService;
	@Autowired
	ApprovalService approvalService;
	@Autowired
	CompanyMaterialCountService companyMaterialCountService;
	@Autowired
	WorkshopService workshopService;
	@Autowired
	PutOutServiceNew putOutServiceNew;
	@Autowired
	BasicDataService basicDataService;
	@Autowired
	PurchaseOrderService purchaseOrderService;
	@Autowired
	FeedOrderService feedOrderService;
	@Autowired
	MaterialPositionService materialPositionService;
	@Autowired
	OtherWarehouseService otherWarehouseService;
	@Autowired
	CompanyService companyService;
	
	
	public static Set<Integer> WAREHOUSE_IN_SET=new HashSet<Integer>();
	public static Set<Integer> WAREHOUSE_OUT_SET=new HashSet<Integer>();
	static {
		WAREHOUSE_IN_SET.add(1);
		WAREHOUSE_IN_SET.add(3);
		WAREHOUSE_IN_SET.add(4);
		WAREHOUSE_IN_SET.add(7);
		WAREHOUSE_IN_SET.add(8);
		WAREHOUSE_IN_SET.add(11);
		
		WAREHOUSE_OUT_SET.add(2);
		WAREHOUSE_OUT_SET.add(5);
		WAREHOUSE_OUT_SET.add(9);
		WAREHOUSE_OUT_SET.add(12);
		
	}
	
	/**
	 * @throws CloneNotSupportedException 
	 * @param request 
	 * 采购单入库
	* @date 2018年9月14日 上午11:27:41 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public String saveWarehouseInByPurchaseOrder(Map<String, String> map, HttpServletRequest request) throws CloneNotSupportedException {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String time=sdf.format(new Date());
		String metailArray=map.get("array").toString();
		JSONArray jsonArray=JSONArray.fromObject(metailArray);
		//前台传过来的物料集合
		List<CompanyMaterialTableBean> listCmtb=(List<CompanyMaterialTableBean>) JSONArray.toCollection(jsonArray, CompanyMaterialTableBean.class);
	    //保存的出入库记录
		List<WarehouseInOutDetailBean> inOutList=new ArrayList<WarehouseInOutDetailBean>();
		//需要处理的采购单List
		List<PurchaseOrderBean> purchaseOrderBeanList = new ArrayList<PurchaseOrderBean>();
		//物料参数map
		Map<String,Object> materialParam = new HashMap<String,Object>();
		//发送消息message
		List<String> message = new ArrayList<String>();
		//仓位物料对应表
		List<MaterialPositionBean> materialPostionList = new ArrayList<MaterialPositionBean>();
		//是否是过账审核
		boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		Map<String,String> aduitMap=this.setAduitMap(map);
		//循环遍历
		for(CompanyMaterialTableBean cmtb:listCmtb) {
			//如果制单人和接受人是同一个人，默认审批，修改库存数
			materialParam.clear();
		    materialParam.put("loginCompany", map.get("loginCompany"));
	    	materialParam.put("materialCode", cmtb.getMaterialCode());
	    	CompanyMaterialTableBean companyMaterialTableBean = companyMaterialMapper.getCompanyMaterialTableByMaterialCode(materialParam);
			this.isCheckMateiral(companyMaterialTableBean,"无法入库");
			//订单采购入库
			if(cmtb.getType()==1 || cmtb.getType()==2) {
				int type;
				if(cmtb.getType()==1) {
					type  =1;
				}else {
					type  =3;
				}
				Integer warehouseType = null;
				Assert.notNull(cmtb.getWarehouseType()==null, "仓库类型为空");
				warehouseType = cmtb.getWarehouseType();
				map.put("purchaseDetailId", cmtb.getPurchaseDetailId());
				PurchaseOrderBean purchaseOrderBean = purchaseOrderMapper.getPurchaseOrderByPurchaseDetailId(map);
				Assert.notNull(purchaseOrderBean, "采购单不存在");
				Assert.isTrue(cmtb.getCount().doubleValue()!=0, "入库数量为0");
				BigDecimal adJustInCount = new BigDecimal(companyMaterialTableBean.getAdJustInCount().toString());
				//采购数
				BigDecimal purchaseCount = new BigDecimal(purchaseOrderBean.getPurchaseCount().toString());
				BigDecimal canInCount=purchaseCount.add(adJustInCount);
				//已入库数
				BigDecimal purchaseInCount = new BigDecimal("0.0");
				//即将入库数
				BigDecimal inCount = new BigDecimal(cmtb.getCount().toString());
				BigDecimal scrapCount = new BigDecimal(cmtb.getScrapCount().toString());
				inCount=inCount.add(scrapCount);
				//如果状态是0 那么就查询出入库状态为0,1 反之状态为1 那么只查询出入库状态为1 
				purchaseOrderBean.setStatus(0);
				List<WarehouseInOutDetailBean> allInCountData = warehouseMapper.getWarehouseInByPurchaseDetail(purchaseOrderBean);
				for(WarehouseInOutDetailBean ware:allInCountData) {
					purchaseInCount = purchaseInCount.add(new BigDecimal(ware.getCount().toString()));
				}
				if(inCount.subtract((canInCount.subtract(purchaseInCount))).doubleValue()>0) {
				    throw new ServiceException(purchaseOrderBean.getMaterialName()+"最多还可入库"+(canInCount.subtract(purchaseInCount)));
			    } 
				 //如果入库数等于采购数状态修改为已完成
			    if(inCount.subtract((purchaseCount.subtract(purchaseInCount))).doubleValue()>=0) {
			    	purchaseOrderBean.setIsFinish(1);
			    }
			    purchaseOrderBeanList.add(purchaseOrderBean);
			    //处理保存入库单
			    WarehouseInOutDetailBean warehouseInOutDetailBean=new WarehouseInOutDetailBean();
			    warehouseInOutDetailBean.setOrderId(cmtb.getOrderId());
			    warehouseInOutDetailBean.setMaterialType(cmtb.getMaterialType());
			    warehouseInOutDetailBean.setRowIndex(cmtb.getRowIndex());
			    warehouseInOutDetailBean.setCount(cmtb.getCount());//入库数量
			    warehouseInOutDetailBean.setCreateTime(time);//入库时间
			    warehouseInOutDetailBean.setCreateUser(map.get("loginUserId").toString());//采购人
			    String rkId = dingTalkMapper.getApprovalNo("RK");
			    warehouseInOutDetailBean.setId(rkId);
			    warehouseInOutDetailBean.setWarehouseType(warehouseType);
			    warehouseInOutDetailBean.setMaterialCode(cmtb.getMaterialCode());//物料代码
			    warehouseInOutDetailBean.setPurcharseOrderId(purchaseOrderBean.getPurchaseDetailId());//入库投料单采购单明细id
			    warehouseInOutDetailBean.setType(type);//类型1为订单采购入库   2为出库 3 为库存才采购单入库
			    warehouseInOutDetailBean.setPosition(cmtb.getPositions());
			    warehouseInOutDetailBean.setInCountPrice(cmtb.getInCountPrice()); //入库结算单位
			    warehouseInOutDetailBean.setInCountUnit(cmtb.getInCountUnit());  //入库结算单价
			    warehouseInOutDetailBean.setWarehouseInType(cmtb.getType());//采购入库类型 1订单采购入库 2库存采购入库
			    warehouseInOutDetailBean.setCompany(map.get("loginCompany").toString());
			    warehouseInOutDetailBean.setSumMoneyCount(cmtb.getSumMoneyCount()); //入库结算数量
			    warehouseInOutDetailBean.setMaterialName(companyMaterialTableBean.getMaterialName());
		    	warehouseInOutDetailBean.setColor(companyMaterialTableBean.getColor());
		    	warehouseInOutDetailBean.setModel(companyMaterialTableBean.getModel());
		    	warehouseInOutDetailBean.setProviderName(cmtb.getProviderName());//此处供应商为采购供应商（经销商）
			    warehouseInOutDetailBean.setStatus(0);
			    warehouseInOutDetailBean.setRemark(cmtb.getRemark());
			    warehouseInOutDetailBean.setInDay("".equals(cmtb.getInDay())?time:cmtb.getInDay());
			    warehouseInOutDetailBean.setInOutUnit(companyMaterialTableBean.getUnit());
			    warehouseInOutDetailBean.setInOutMoney(cmtb.getInOutMoney());
			    warehouseInOutDetailBean.setScrapCount(cmtb.getScrapCount());
			    warehouseInOutDetailBean.setIsTax(cmtb.getIsTax());
			    inOutList.add(warehouseInOutDetailBean);
			    message.add(rkId);
			}
			//插入入库记录
		    if(inOutList !=null && inOutList.size()>0) {
		    	purchaseOrderMapper.updatePurchaseOrderOnFinish(purchaseOrderBeanList);
		    	purchaseOrderBeanList.clear();
		    	this.checkTakingIsNotApproval(inOutList, map.get("loginCompany"));
		    	companyMaterialMapper.insertInOutRecode(inOutList);
		    	if(isAduit) {
					aduitMap.put("id", inOutList.get(0).getId());
					this.approvalWarehouse(aduitMap,1,request);
				}
		    	inOutList.clear();
		    } 
		}
//		if(materialPostionList.size()>0) {
//	    	Map<String,Object> paramMap = new HashMap<String,Object>();
//	    	paramMap.put("materialPositionList", materialPostionList);
//	    	materialPositionService.addMaterialPositionList(paramMap);
//	    }
		String msg = "";
		
	    if(!isAduit){
			/** 
			 * 发消息提示需审核
			 */ 
			if(message.size()>0) {
				String bodyMessage = "条采购入库单需审核";
				String queryCondition = "?ids="+message.toString().substring(1,message.toString().length()-1).replace(" ","");
				msg = companyMaterialService.sendWechatMessage("入库单待审核", 2, message.size()+bodyMessage, sdf.format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 1);
			}
		}
	    return msg;
	} 
	
	
	

	/**
	 * 设置过账审核的map信息
	 * @param map
	 * @return
	 */
	public  Map setAduitMap(Map map) {
		Map aduitMap=new HashMap();
		aduitMap.put("loginCompany", map.get("loginCompany"));
		aduitMap.put("loginUserName", map.get("loginUserName"));
		aduitMap.put("loginUserId", map.get("loginUserId"));
		aduitMap.put("loginUserDeptId", map.get("loginUserDeptId"));
		aduitMap.put("loginUserPhone", map.get("loginUserPhone"));
		aduitMap.put("loginUserOpenId", map.get("loginUserOpenId"));
		aduitMap.put("loginCompanyId", map.get("loginCompanyId"));
		aduitMap.put("isAduit", "true");
		return aduitMap;
	}




	/**
	 * @throws CloneNotSupportedException 
	 * @param request 
	 * 无采购单入库
	* @date 2018年9月15日 下午3:11:12 
	* @author 李斌
	* @return String 
	* @throws 
	 */
	public String saveWarehouseNotPurchaseOrder(Map<String, String> map, HttpServletRequest request) throws CloneNotSupportedException {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String time=sdf.format(new Date());
		String metailArray=map.get("array").toString();
		JSONArray jsonArray=JSONArray.fromObject(metailArray);
		//前台传过来的物料集合
		List<CompanyMaterialTableBean> listCmtb=(List<CompanyMaterialTableBean>) JSONArray.toCollection(jsonArray, CompanyMaterialTableBean.class);
		//保存的出入库记录
		List<WarehouseInOutDetailBean> inOutList=new ArrayList<WarehouseInOutDetailBean>();
		//发送消息用的集合
		Map<String,Object> materialParam = new HashMap<String,Object>(); 
		List<MaterialPositionBean> materialPostionList = new ArrayList<MaterialPositionBean>();
		materialParam.put("loginCompany", map.get("loginCompany"));
		List<String> idList = new ArrayList<String>();
		//是否是过账审核
		boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		Map<String,String> aduitMap=this.setAduitMap(map);
		for(CompanyMaterialTableBean cmtb:listCmtb) {
			materialParam.put("materialCode",cmtb.getMaterialCode());
	    	CompanyMaterialTableBean companyMaterialTableBean = companyMaterialMapper.getCompanyMaterialTableByMaterialCode(materialParam);
	    	this.isCheckMateiral(companyMaterialTableBean,"无法入库");
    		Assert.isTrue(cmtb.getCount().doubleValue()!=0, "入库数量为0");
    		Double count = cmtb.getCount();
		    WarehouseInOutDetailBean warehouseInOutDetailBean=new WarehouseInOutDetailBean();
		    warehouseInOutDetailBean.setCount(count);//入库数量
		    warehouseInOutDetailBean.setCreateTime(time);//入库时间
		    warehouseInOutDetailBean.setCreateUser(map.get("loginUserId").toString());
		    String rkId = dingTalkMapper.getApprovalNo("RK");
		    warehouseInOutDetailBean.setId(rkId);
		    warehouseInOutDetailBean.setMaterialCode(cmtb.getMaterialCode());//物料代码
		    warehouseInOutDetailBean.setPurcharseOrderId("无采购单不增物料入库");//入库投料单采购单对应表Id
		    warehouseInOutDetailBean.setType(4);
		    warehouseInOutDetailBean.setPosition(cmtb.getPositions());
		    warehouseInOutDetailBean.setMaterialName(cmtb.getMaterialName());
		    warehouseInOutDetailBean.setColor(cmtb.getColor());
		    warehouseInOutDetailBean.setModel(cmtb.getModel());
		    warehouseInOutDetailBean.setProviderName(cmtb.getProviderName());
		    warehouseInOutDetailBean.setRemark(cmtb.getRemark());
		    warehouseInOutDetailBean.setOutCountPrice(cmtb.getOutCountPrice());
		    if(cmtb.getInCountPrice()!=null) {
		    	warehouseInOutDetailBean.setInCountPrice(cmtb.getInCountPrice());
		    }
		    warehouseInOutDetailBean.setWarehouseType(cmtb.getWarehouseType());
	    	warehouseInOutDetailBean.setStatus(0); 
		    warehouseInOutDetailBean.setInOutUnit(companyMaterialTableBean.getUnit());		    //入库单位
		    warehouseInOutDetailBean.setWarehouseInType(4);//采购入库类型 1订单采购入库 2库存采购入库 无采购单入库
		    warehouseInOutDetailBean.setCompany(map.get("loginCompany").toString());
		    //入库结算数量
		    warehouseInOutDetailBean.setSumMoneyCount(cmtb.getSumMoneyCount());
		    //入库结算单位
		    warehouseInOutDetailBean.setInCountUnit(cmtb.getInCountUnit());
		    warehouseInOutDetailBean.setInDay("".equals(cmtb.getInDay())?time:cmtb.getInDay());
		    warehouseInOutDetailBean.setInOutMoney(cmtb.getInOutMoney());
		    warehouseInOutDetailBean.setIsTax(cmtb.getIsTax());
		    inOutList.add(warehouseInOutDetailBean);
		    idList.add(warehouseInOutDetailBean.getId());
	    	//插入入库记录 
		    if(inOutList !=null && inOutList.size()>0) {
		    	this.checkTakingIsNotApproval(inOutList, map.get("loginCompany"));
		    	companyMaterialMapper.insertInOutRecode(inOutList);
		    	if(isAduit) {
					aduitMap.put("id", inOutList.get(0).getId());
					this.approvalWarehouse(aduitMap,1,request);
				}
		    	inOutList.clear();
		    }
//		    MaterialPositionBean materialPosition = new MaterialPositionBean();
//		    materialPosition.setMaterialCode(warehouseInOutDetailBean.getMaterialCode());
//		    materialPosition.setPosition(warehouseInOutDetailBean.getPosition());
//		    materialPosition.setCompany(warehouseInOutDetailBean.getCompany());
//		    materialPostionList.add(materialPosition);
	    } 
//		if(materialPostionList.size()>0) {
//	    	Map<String,Object> paramMap = new HashMap<String,Object>();
//	    	paramMap.put("materialPositionList", materialPostionList);
//	    	materialPositionService.addMaterialPositionList(paramMap);
//	    }
		String mString="";
		 if(!isAduit){
			 String queryCondition = "?ids="+idList.toString().substring(1,idList.toString().length()-1).replace(" ","");
			 mString=companyMaterialService.sendWechatMessage("无采购入库单", 2, "无采购入库待审批通知", sdf.format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 1);
		 }
		//发送微信消息
		return mString;
	}
	
	
	/**
	 * @throws CloneNotSupportedException 
	 * 保存出库单(包括发料单)
	* @date 2018年9月15日 下午3:34:54 
	* @author 李斌
	* @return String 
	* @throws
	 */
	public String saveWarehouseOut(Map<String, String> map,HttpServletRequest request) throws CloneNotSupportedException {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String dataString=sdf.format(new Date());
		String metailArray=map.get("metailArray").toString();
		JSONArray jsonArray=JSONArray.fromObject(metailArray);
		//前台传输数据
		List<WarehouseInOutDetailBean> inOutList=(List<WarehouseInOutDetailBean>) JSONArray.toCollection(jsonArray, WarehouseInOutDetailBean.class);
        List<WarehouseInOutDetailBean> saveList = new ArrayList<WarehouseInOutDetailBean>();
		//要修改的投料单信息
		List<FeedOrderDetailBean> feedList=new ArrayList<FeedOrderDetailBean>();
		Map<String,Object> paramMap=new HashMap<String,Object>();
		/**
	     * 需要发送信息的数据
	     * List
	     */
		List<String> message = new ArrayList<String>();
		boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		//遍历出库数据
		for(WarehouseInOutDetailBean inOut:inOutList) {
			  Assert.notNull(inOut.getWarehouseType(), "出库仓库为空");
			  inOut.setCreateTime(dataString);
			  String rkId = dingTalkMapper.getApprovalNo("CK");
			  message.add(rkId);
			  inOut.setId(rkId); 
			  inOut.setCreateUser(map.get("loginUserId").toString());
			  inOut.setStatus(0);
			  inOut.setCompany(map.get("loginCompany").toString());
			  inOut.setConfirmStatus(0);
			  inOut.setApprovalTime(null);
			  paramMap.put("materialCode",inOut.getMaterialCode());
			  paramMap.put("loginCompany",map.get("loginCompany"));
			  CompanyMaterialTableBean cmtb=companyMaterialMapper.getCompanyMaterialTableByMaterialCode(paramMap);
			  //获取原材料和辅料仓的物料合计
			  CompanyMaterialCountBean companyMaterialCountBean = companyMaterialCountService.getCompanyMaterialCountByMaterial(paramMap);
			  BigDecimal outCount = new BigDecimal(inOut.getCount().toString());;
			  if(inOut.getIsProductionUnit().equals(0)) {
				  inOut.setInOutUnit(cmtb.getUnit());
				  inOut.setIsEquals(1);
			  }else {
				  inOut.setInOutUnit("付");	
				  inOut.setIsEquals(0);
			  } 
			  this.isCheckMateiral(cmtb,"无法出库");
			  //校验库存数
			  this.checkMaterialCount(companyMaterialCountBean,cmtb,inOut);
			  //出入库单位
			  if(inOut.getType()==5) {
				  //库存数
				  Map<String,Double> mapCount = otherWarehouseMapper.getCountResult(inOut.getMaterialCode(), map.get("loginCompany").toString());
				  //库存数量
				  BigDecimal materialReceiveCount =new BigDecimal("0.0");
					//采购数
				  BigDecimal purchaseCount = new BigDecimal("0.0");
					//排除订单的库存数
				  BigDecimal notOrderMaterialCount = new BigDecimal("0.0");
					//所有投料数
				  BigDecimal allFeedCount = new BigDecimal("0.0");
				  if(mapCount.get("purchaseCount")!=null) {
						purchaseCount = new BigDecimal(mapCount.get("purchaseCount").toString());
				  }
			      if(mapCount.get("feedCount")!=null) {
						allFeedCount = new BigDecimal(mapCount.get("feedCount").toString());
				  }
				  if(mapCount.get("stockCount")!=null) {
						notOrderMaterialCount = new BigDecimal(mapCount.get("stockCount").toString());
				  }
				  materialReceiveCount = purchaseCount.add(notOrderMaterialCount).subtract(allFeedCount); 
				  if(outCount.subtract(materialReceiveCount).doubleValue()>0) {
					  throw new ServiceException("领料数不能大于库存可用数"+(materialReceiveCount.doubleValue()<0?0:materialReceiveCount.doubleValue())+",当前库存数量被其他订单占用");
				  } 
			  }else if(inOut.getType()==2) { 
				  //物料单位库存数
				  BigDecimal materialCount = new BigDecimal(companyMaterialCountBean.getCount().toString());
				  //生产单位库存数
				  BigDecimal productionUnitCount = new BigDecimal(companyMaterialCountBean.getProductionUnitCount().toString());
				  //物料单位
				  if(inOut.getIsProductionUnit().equals(0)) {
					  if(outCount.subtract(materialCount).doubleValue()>0) {
						  throw new ServiceException("物料单位领料数不能大于物料单位库存数"+companyMaterialCountBean.getCount());
					  }
					  //生产单位
				  }else if(inOut.getIsProductionUnit().equals(1)) {
					  if(outCount.subtract(productionUnitCount).doubleValue()>0) {
						  throw new ServiceException("生产单位领料数不能大于生产单位库存数"+companyMaterialCountBean.getProductionUnitCount());
					  }
				  }else {//未知异常
					  throw new ServiceException("既不是生产单位领料,也不是物料单位领料异常");
				  }
				  //如果是领料单出库 就在出库明细里面加上
				  if(map.get("loginUserDeptId")==null) {
					  throw new ServiceException("操作人部门id为空");
				  }
				  //如果不是发料单
				  if(inOut.getSourceType() == null || inOut.getSourceType() != 1 ) {
					  UserBean userBean = userService.getUserById(map); 
					  //判断用户是否有车间,如果没有就选择部门反之选择车间
					  if(userBean.getWorkShop()==null||userBean.getWorkShop().trim().equals("") || userBean.getWorkShop().trim().equals("0")) {
						  throw new ServiceException("无车间的人员不能领料");
					  }else {  
						  inOut.setDeptId(userBean.getDeptName());
						  inOut.setWorkShopId(userBean.getWorkShop());
					  } 
				  }
				  //通过出库数据查找投料单明细
				  FeedOrderDetailBean feedDeatil=orderService.getFeedOrderDetailOneById(inOut.getFeedOrder());
				  //物料单位投料数
				  BigDecimal feedCount = new BigDecimal(feedDeatil.getActualFeedCount().toString());
				  //物料单位领料数
				  BigDecimal receiveCont = new BigDecimal(feedDeatil.getReceiveCount().toString());
				  //生产单位投料数
				  BigDecimal productionUnitFeedCount = new BigDecimal(feedDeatil.getProductionUnitFeedCount().toString());
				  //生产单位领料数
				  BigDecimal productionUnitReceiveCount = new BigDecimal(feedDeatil.getProductionUnitReceiveCount().toString());
				  //物料单位
				  if(inOut.getIsProductionUnit().equals(0)) {
					  if(outCount.subtract(feedCount.subtract(receiveCont)).doubleValue()>0) {
						  throw new ServiceException("该投料单物料单位领料数,最多还可领料"+(feedCount.subtract(receiveCont).doubleValue()));
					  }
					  feedDeatil.setReceiveCount(receiveCont.add(outCount).doubleValue());
					  //生产单位
				  }else if(inOut.getIsProductionUnit().equals(1)) {
					  if(outCount.subtract(productionUnitFeedCount.subtract(productionUnitReceiveCount)).doubleValue()>0) {
						  throw new ServiceException("该投料单生产单位领料数,最多还可领料"+(productionUnitFeedCount.subtract(productionUnitReceiveCount).doubleValue()));
					  } 
					  feedDeatil.setProductionUnitReceiveCount(productionUnitReceiveCount.add(outCount).doubleValue());
				  }else {//未知异常
					  throw new ServiceException("既不是生产单位领料,也不是物料单位领料异常");
				  }
				  //物料单位领料完成并且生产单位领料完成才能算是真正的完成领料了
				  if(inOut.getIsProductionUnit().equals(0)) {
					  //如果当前是物料单位出库,那么 receiveCount = receiveCount+outCount
					  if(receiveCont.add(outCount).subtract(feedCount).doubleValue()==0 && productionUnitReceiveCount.subtract(productionUnitFeedCount).doubleValue()==0) {
						  feedDeatil.setIsReceiveFinish(1);
					  }else {
						  feedDeatil.setIsReceiveFinish(0);
					  }
				  }else {
					  //如果当前是生产单位出库,那么 productionUnitReceiveCount = productionUnitReceiveCount+outCount
					  if(receiveCont.subtract(feedCount).doubleValue()==0 && productionUnitReceiveCount.add(outCount).subtract(productionUnitFeedCount).doubleValue()==0) {
						  feedDeatil.setIsReceiveFinish(1);
					  }else {
						  feedDeatil.setIsReceiveFinish(0);
					  }
				  }
				  //校验是否领完
				  boolean isFinish = checkFeedOrderIsFinish(feedDeatil,inOut,false,0);
				  if(isFinish) {
					  feedDeatil.setIsReceiveFinish(1);
				  }
				  feedList.add(feedDeatil);
			  }else {
				   throw new ServiceException("未知类型出库异常"); 
			  }
			  saveList.add(inOut);  
			  //插入出库记录
		      if(saveList !=null && saveList.size()>0) {
		    	this.checkTakingIsNotApproval(saveList, map.get("loginCompany"));
		    	companyMaterialMapper.insertInOutRecode(saveList);
		    	if(isAduit) {
					Map<String,String> aduitMap=this.setAduitMap(map);
					aduitMap.put("id", inOut.getId());
					this.approvalWarehouse(aduitMap,1,request);
				}
		    	saveList.clear();
		      } 
		      //修改投料单明细的领料数
		      paramMap.put("feedList", feedList);
		      companyMaterialMapper.updateFeedOrderDetailReceive(paramMap);
		      paramMap.remove("feedList");
		      feedList.clear();
		} 
	    /**
	     * 发送消息
	     */ 
	    String msg = "";
	    try {
		    if(message.size()>0) {
		    	if(inOutList.get(0).getSourceType()!=null && inOutList.get(0).getSourceType().intValue()==1) { 
		    		int orderType = 4;
		    		if(inOutList.get(0).getSource() !=null && inOutList.get(0).getSource().intValue()==2) {
		    			orderType  =5;
		    		}else {
		    			map.put("pickingPeople", inOutList.get(0).getPickingPeople()); 
		    		}
		    		String bodyMessage = "条发料单需审核";
			    	String queryCondition = "?ids="+message.toString().substring(1,message.toString().length()-1).replace(" ","");
			    	msg = companyMaterialService.sendWechatMessage("发料单待审核",orderType, message.size()+bodyMessage, sdf.format(new Date()), map, RedirectUrlUtil.QUERY_ISSUE_NOTE+queryCondition, 0);
		    	}else {
		    		String bodyMessage = "条出库单需审核";
			    	String queryCondition = "?ids="+message.toString().substring(1,message.toString().length()-1).replace(" ","");
			    	msg = companyMaterialService.sendWechatMessage("出库单待审核", 2, message.size()+bodyMessage, sdf.format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 2);
		    	}
		    }
	    }catch(Exception e) {
	    	msg =  "发送消息失败";
	    }
	    return msg==null?"":msg;
	}
	
	/**
	 * 批量审核出入库记录
	 * @param map
	 * @param status
	 * @return
	 * @throws CloneNotSupportedException 
	 */
	public String approvalAllWarehouse(Map<String, String> map, int status,HttpServletRequest request) throws CloneNotSupportedException {
		StringUtil.checkIsTrue(map, "ids", "未获取到参数");
		String idString=map.get("ids").toString();
		JSONArray jsonArray=JSONArray.fromObject(idString);
		List<WarehouseInOutDetailBean> list=(List<WarehouseInOutDetailBean>) JSONArray.toCollection(jsonArray, WarehouseInOutDetailBean.class);
		String message = "";
		for(WarehouseInOutDetailBean bean:list) {
			map.put("id", bean.getId());
			map.put("isApproval", bean.getIsApproval());
			message = approvalWarehouse(map,status,request);
		}
		return message;
	}
	
	/**
	 * @throws CloneNotSupportedException 
	 * 审核出入库
	* @date 2018年9月15日 下午4:15:32 
	* @author 李斌
	* @return String 
	* @throws
	 */
	public String approvalWarehouse(Map<String, String> map,int status,HttpServletRequest request) throws CloneNotSupportedException {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//判断审核权限
		WarehouseInOutDetailBean wiodb=companyMaterialMapper.getInWarehourseByIdOne(map.get("id"));
		Assert.isTrue(wiodb!=null, "该出入库单已被删除,审核失败");
		Assert.isTrue(wiodb.getStatus()==0, "该出入库单已经审核了,请勿重复操作!");
		String isApprovals = map.get("isApproval");
		Map<String, Object> approvalParam = new HashMap<String,Object>();
		approvalParam.put("loginUserId", map.get("loginUserId"));
		approvalParam.put("loginCompany", map.get("loginCompany"));
		//此参数只有在发料单中会传
		if(isApprovals==null || !"1".equals(isApprovals.toString())) {
			
			if(wiodb.getSourceType()==5) {
				approvalParam.put("type","12"); 
			}else {
				approvalParam.put("type","6"); 
			}
			//查询本人可审核人
			List<String> userIds = approvalService.getApprovalIdByLoginId(approvalParam);
			Assert.isTrue(null!=userIds && userIds.contains(wiodb.getCreateUser()), "您暂无权限审核此出入库单!");
		}else {
			//如果是出库到外协
			if(wiodb.getSource()==2) {
				approvalParam.put("request", request);
				putOutServiceNew.checkPutOutApprovalPermission(approvalParam);
			}else {
				Assert.isTrue(wiodb.getPickingPeople().equals(map.get("loginUserId")), "您暂无权限审核此出入库单!");
			}
			
		}
		//判断仓库
		Assert.notNull(wiodb.getWarehouseType(), "仓库类型为空异常");
		//获取物料信息
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("materialCode", wiodb.getMaterialCode());
		paramMap.put("loginCompany", map.get("loginCompany"));
		CompanyMaterialTableBean cmtb = companyMaterialMapper.getCompanyMaterialTableByMaterialCode(paramMap);
		//成品仓不校验物料
		if(wiodb.getWarehouseType().intValue() != 1) {
			this.isCheckMateiral(cmtb, "审核出入库单失败");
		}else {
			paramMap.put("orderId", wiodb.getOrderId());
			paramMap.put("rowIndex", wiodb.getRowIndex());
		}
		paramMap.put("warehouseType", wiodb.getWarehouseType());
		//获取仓库库存信息   和出入库信息同一个仓位的库存数
		List<CompanyMaterialCountBean> companyMaterialCountBeans = companyMaterialCountService.getCompanyMaterialCountListByDetail(paramMap);
		Assert.isTrue((null==companyMaterialCountBeans?0:companyMaterialCountBeans.size())<2, "多条库存信息异常");
		if(companyMaterialCountBeans==null || companyMaterialCountBeans.size()<1) {//如果没有库存记录,增加一个库存记录
			CompanyMaterialCountBean companyMaterialCountBean = new CompanyMaterialCountBean();
			companyMaterialCountBean.setCount(0.0);
			companyMaterialCountBean.setNoCount(0.0);
			companyMaterialCountBean.setProductionUnitCount(0.0);
			companyMaterialCountBean.setProductionUnitNoCount(0.0);
			//除了成品仓，其他仓位不需要单号
			if(wiodb.getWarehouseType().intValue() == 1) {
				companyMaterialCountBean.setOrderId(wiodb.getOrderId());
				companyMaterialCountBean.setRowIndex(Integer.valueOf(wiodb.getRowIndex()));
			}
			companyMaterialCountBean.setCompany(map.get("loginCompany"));
			companyMaterialCountBean.setWarehouseType(wiodb.getWarehouseType());
			companyMaterialCountBean.setMaterialCode(wiodb.getMaterialCode());
			companyMaterialCountService.addCompanyMaterialCount(companyMaterialCountBean);
			paramMap.put("companyMaterialCount", companyMaterialCountBean);
		}else {
			paramMap.put("companyMaterialCount", companyMaterialCountBeans.get(0));
		}
		paramMap.put("cmtb",cmtb);
		paramMap.put("loginUserId",map.get("loginUserId"));
		paramMap.put("loginUserName",map.get("loginUserName"));
		//是否捕获异常
		paramMap.put("isTcy", map.get("isTcy"));
		wiodb.setStatus(status);
		wiodb.setApprovalReason(map.get("approvalReason"));
		wiodb.setApprovalTime(simpleDateFormat.format(new Date()));
		wiodb.setApprovalUser(map.get("loginUserId"));
		//确认后返回信息
		String confirmMsg = null; 
		if(status == 1) {
			try {
				confirmMsg = this.confirmWarehouse(wiodb,paramMap);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else if(status==2) {
			//1 代表第一次返回
			this.returnWarehouse(wiodb,paramMap,1);
		}else {
			throw new ServiceException("未知状态");
		}
		int row = warehouseMapper.updateWarehouInOutOnStatus(wiodb);
		Assert.isTrue(row>0,"审核出入库失败");
		if(confirmMsg !=null) {
			return confirmMsg;
		}
		String type = "入库单";
		//跳转地址
		String redirectUrl = RedirectUrlUtil.queryWarehouse;
		if(wiodb.getType()==2||wiodb.getType()==5 || wiodb.getType()==9) {
			if(wiodb.getSourceType()!=null && wiodb.getSourceType()==1) {
				type = "发料单";
				redirectUrl = RedirectUrlUtil.QUERY_ISSUE_NOTE;
			}else {
				type = "出库单";
			}
			if(wiodb.getWarehouseType() == 1) {
				redirectUrl = RedirectUrlUtil.queryFinishWarehouse;
			}
			
		}
		//校验出库是否完成  是审核通过,是出库给客户，
		if(status == 1 && 9 == wiodb.getType() && 1==wiodb.getWarehouseType()) {
			 this.checkOrderFinish(wiodb.getOrderId());
		}
//		Assert.isTrue(false,"截断");
		//发送库存不足信息
		this.sendUunderStockMessage(wiodb,(CompanyMaterialCountBean)paramMap.get("companyMaterialCount"), cmtb, simpleDateFormat.format(new Date()), paramMap);
		//发送出入库审核信息
		String approvalMsg ="";
	    boolean bool=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
	    if(!bool) {
			approvalMsg=workshopService.sendApprovalStatusMassage(status, wiodb.getCreateUser(), map.get("loginUserName").toString(), type, redirectUrl+"#id="+wiodb.getId());
		}
		return "操作成功 "+approvalMsg;
	}
	
	/**
	 * 校验订单是否完成
	 * @param wiodb
	 */
	private void checkOrderFinish(String orderId) {
		OrderBean orderBean = orderService.getOrderByOrderId(orderId) ;
		double  toCoustomCount = warehouseMapper.getOrderToCoustomCount(orderId);
		if(toCoustomCount>=orderBean.getOrderCount()) {
			warehouseMapper.setOrderFinish(orderId);
		}
	}




	/**
	 * 出入库记录审核后退回功能
	 * id
	 * @param map
	 * @param status
	 * @param request
	 * @return
	 * @throws CloneNotSupportedException
	 */
	public String toVoidInOutRecord(Map<String, String> map) throws CloneNotSupportedException {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//判断审核权限
		WarehouseInOutDetailBean wiodb=companyMaterialMapper.getInWarehourseByIdOne(map.get("id"));
		Assert.isTrue(wiodb!=null, "该出入库单已被删除,操作失败");
		Assert.isTrue(wiodb.getStatus()==1, "该出入库记录不是审核状态");
		//判断仓库
		Assert.notNull(wiodb.getWarehouseType(), "仓库类型为空异常");
		//获取物料信息
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("materialCode", wiodb.getMaterialCode());
		paramMap.put("loginCompany", map.get("loginCompany"));
		CompanyMaterialTableBean cmtb = companyMaterialMapper.getCompanyMaterialTableByMaterialCode(paramMap);
		//成品仓不校验物料
		if(wiodb.getWarehouseType().intValue() != 1) {
			//校验物料是否存在，是否被禁用
			this.isCheckMateiral(cmtb, "审核出入库单失败");
		}else {
			paramMap.put("orderId", wiodb.getOrderId());
			paramMap.put("rowIndex", wiodb.getRowIndex());
		}
		paramMap.put("warehouseType", wiodb.getWarehouseType());
		//获取仓库库存信息   和出入库信息同一个仓位的库存数
		List<CompanyMaterialCountBean> companyMaterialCountBeans = companyMaterialCountService.getCompanyMaterialCountListByDetail(paramMap);
		//判断退回类型，做不同的处理
		this.checkReturnWarehouseInOutType(wiodb,companyMaterialCountBeans.get(0),cmtb,map.get("loginUserId"));
		
		paramMap.put("companyMaterialCount", companyMaterialCountBeans.get(0));
		paramMap.put("cmtb",cmtb);
		paramMap.put("loginUserId",map.get("loginUserId"));
		paramMap.put("loginUserName",map.get("loginUserName"));
		
		//是否捕获异常
		paramMap.put("isTcy", map.get("isTcy"));
		wiodb.setStatus(2);
		wiodb.setApprovalReason("审核后强制退回");
		wiodb.setApprovalTime(simpleDateFormat.format(new Date()));
		wiodb.setApprovalUser(map.get("loginUserId"));
		//确认后返回信息
		String confirmMsg = null; 
		//二代表审核后退回
		this.returnWarehouse(wiodb,paramMap,2);
		int row = warehouseMapper.updateWarehouInOutOnStatus(wiodb);
		Assert.isTrue(row>0,"审核出入库失败");
		//更新库存
		
		if(confirmMsg !=null) {
			return confirmMsg;
		}
		String type = "入库单";
		//跳转地址
		String redirectUrl = RedirectUrlUtil.queryWarehouse;
		if(wiodb.getType()==2||wiodb.getType()==5 || wiodb.getType()==9) {
			if(wiodb.getSourceType()!=null && wiodb.getSourceType()==1) {
				type = "发料单";
				redirectUrl = RedirectUrlUtil.QUERY_ISSUE_NOTE;
			}else {
				type = "出库单";
			}
		}
//		//发送库存不足信息
		this.sendUunderStockMessage(wiodb,(CompanyMaterialCountBean)paramMap.get("companyMaterialCount"), cmtb, simpleDateFormat.format(new Date()), paramMap);
//		//发送出入库审核信息
		String approvalMsg =workshopService.sendApprovalStatusMassage(2, wiodb.getCreateUser(), map.get("loginUserName").toString(), type, redirectUrl);
		return "操作成功 "+approvalMsg;
	}
	
	/**
	 * 校验是否有冲销权限
	 * @param map
	 */
	public  Boolean checkToVoidInOutRecordPermission(MyUser myUser) {
		if(myUser.getIsManager() == 1) {
			return true;
		}
		Map map=new HashMap();
		map.put("loginCompany", myUser.getCompany());
		CompanyBean companyBean=companyService.getCompany(map);
		if(companyBean.getInOutReturnUser().equals(myUser.getUserId())) {
			return true;
		}
		return false;
	}




	/**
	 * 校验出入库来源
	 * @param wiodb 出入库记录
	 * @param companyMaterialCountBean 库存信息
	 * @param cmtb 
	 * @param string 
	 */
	private void checkReturnWarehouseInOutType(WarehouseInOutDetailBean wiodb, CompanyMaterialCountBean companyMaterialCountBean, CompanyMaterialTableBean cmtb, String loginUserId) {
		BigDecimal stockCount=new BigDecimal(companyMaterialCountBean.getCount());//库存数
		BigDecimal productionUnitCount=new BigDecimal(companyMaterialCountBean.getProductionUnitCount());//库存数
		BigDecimal warehouseCount=new BigDecimal(wiodb.getCount());
		//物料转仓
		Assert.isTrue(!((wiodb.getType()==11 || wiodb.getType() == 12) && wiodb.getSourceType()==6),"转仓物料不支持审核后退回");
		//是入库
		if(this.WAREHOUSE_IN_SET.contains(wiodb.getType()) || (wiodb.getType()==0 && wiodb.getSource()==1)) {
			//物料单位和出入库单位相同或者成品仓，比物料库存
			if( wiodb.getWarehouseType()==1 || cmtb.getUnit().equals(wiodb.getInOutUnit()) ) {
			    Assert.isTrue(companyMaterialCountBean.getCount()>=wiodb.getCount(),"库存已消耗，不可操作");
			    companyMaterialCountBean.setCount(stockCount.subtract(warehouseCount).doubleValue());
			}else {//比生产单位库存
				Assert.isTrue(companyMaterialCountBean.getProductionUnitCount()>=wiodb.getCount(),"库存已消耗，不可操作");
				companyMaterialCountBean.setProductionUnitCount(productionUnitCount.subtract(warehouseCount).doubleValue());
			}
			
		}else if(this.WAREHOUSE_OUT_SET.contains(wiodb.getType())){
			//投料单出库到车间
			if(wiodb.getType() == 2 && wiodb.getSource() ==0) {
				ReportBean report=new ReportBean();
				report.setWorkShopName(wiodb.getWorkShopId());
				report.setOrderId(wiodb.getOrderId());
				report.setMachining(wiodb.getMaterialType());
				report.setMaterialCode(wiodb.getMaterialCode());
				report.setRowIndex(wiodb.getRowIndex());
				//车间剩余数量
				long  workShopCount = workshopService.getOrderTurnoverCount(report);
				List<ReportBean> reportBeans = workshopService.getReportBeanByOtherId(wiodb.getId());
				if(reportBeans.size()>0) {
					Assert.isTrue(workShopCount>=reportBeans.get(0).getQualified(),"交接到车间的物料已被使用，车间库存不足");
					SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					Map map =new HashMap();
					map.put("loginUserId",loginUserId );
					map.put("status", 2);
					map.put("approvalReason", "审核后强制退回");
					map.put("time", simpleDateFormat.format(new Date()));
					map.put("id", "");
					map.put("otherId", wiodb.getId());
					workshopService.approvalReportByOtherId(map);
				}
			}
			
			//投料单出库到外协
			if(wiodb.getType() == 2 && wiodb.getSource() ==2) {
				PutOutWarehouseBean putOut=new PutOutWarehouseBean();
				putOut.setOrderId(wiodb.getOrderId());
				putOut.setMaterialType(wiodb.getMaterialType());
				putOut.setRowIndex(wiodb.getRowIndex());
				putOut.setMaterialCode(wiodb.getMaterialCode());
				long putOutCount=putOutServiceNew.getPutOutWarehouseStockCount(putOut);
				List<PutOutWarehouseBean> list=putOutServiceNew.getPutOutWarehouseByOtherId(wiodb.getId());
				Assert.isTrue(list.size()>0,"关联的外协记录不存在");
				Assert.isTrue(putOutCount>=list.get(0).getCount());
				Map map=new HashMap();
				map.put("loginUserId", loginUserId);
				map.put("status", 2);
				map.put("otherId", wiodb.getId());
				putOutServiceNew.approvalPutOutWarehouseByOtherId(map);
			}
			
			if( wiodb.getWarehouseType()==1 || cmtb.getUnit().equals(wiodb.getInOutUnit()) ) {
//			    Assert.isTrue(companyMaterialCountBean.getCount()>=wiodb.getCount(),"库存已消耗，不可操作");
			    companyMaterialCountBean.setCount(stockCount.add(warehouseCount).doubleValue());
			}else {//比生产单位库存
//				Assert.isTrue(companyMaterialCountBean.getProductionUnitCount()>=wiodb.getCount(),"库存已消耗，不可操作");
				companyMaterialCountBean.setProductionUnitCount(productionUnitCount.add(warehouseCount).doubleValue());
			}
//			Assert.isTrue(false,"截断");
//			companyMaterialCountBean.setCount(stockCount.add(warehouseCount).doubleValue());
		}		
		companyMaterialCountService.updateCompanyMaterialCountOnCountByMaterialCodeAndWarehouseType(companyMaterialCountBean);
	}




	/**
	 * @param wiodb
	 * @param map
	 * @param returnType  返回类型 第一次退回1   审核后退回2 
	 * @return 
	 * @throws CloneNotSupportedException 
	 */
	public String returnWarehouse(WarehouseInOutDetailBean wiodb,Map<String,Object> map,int returnType) throws CloneNotSupportedException {
		Map<String,String> paramMap = new HashMap<String,String>();
		//采购单退回
		if(wiodb.getType()==1 || wiodb.getType()==3) {
			paramMap.put("purchaseDetailId", wiodb.getPurcharseOrderId());
			paramMap.put("loginCompany", map.get("loginCompany").toString());
			PurchaseOrderBean purchaseOrderBean = purchaseOrderMapper.getPurchaseOrderByPurchaseDetailId(paramMap);
			purchaseOrderBean.setIsFinish(0);
			//如果是审核后退回，需要更改入库数量
			if(returnType==2) {
				purchaseOrderBean.setInCount(purchaseOrderBean.getInCount()-wiodb.getCount()>0?purchaseOrderBean.getInCount()-wiodb.getCount():0);
			}
			List<PurchaseOrderBean> purchaseOrderBeanList = new ArrayList<PurchaseOrderBean>();
			purchaseOrderBeanList.add(purchaseOrderBean);
			purchaseOrderMapper.updatePurchaseOrderOnFinish(purchaseOrderBeanList);
			if(wiodb.getScrapCount()>0 && wiodb.getRalationWarehouse() != -1 && returnType==2) {
		    	WarehouseInOutDetailBean ff=companyMaterialMapper.getInWarehourseByOtherIdOne(wiodb.getId());
		    	Map<String,String> map2=new HashMap<>();	
		    	map2.put("loginCompany", map.get("loginCompany").toString());
		    	map2.put("loginUserName", map.get("loginUserName").toString());
		    	map2.put("id", ff.getId());
		    	this.toVoidInOutRecord(map2);
		    }
		}else if(wiodb.getType()==2) {
		//投料单出库退回
			List<FeedOrderDetailBean> feedList = new ArrayList<FeedOrderDetailBean>();
			CompanyMaterialTableBean cmtb = (CompanyMaterialTableBean) map.get("cmtb");
			FeedOrderDetailBean feedDeatil=orderService.getFeedOrderDetailOneById(wiodb.getFeedOrder());
			if(cmtb.getUnit().equals(wiodb.getInOutUnit())) {
				BigDecimal receiveCount = new BigDecimal(feedDeatil.getReceiveCount().toString());
				BigDecimal count = new BigDecimal(wiodb.getCount().toString());
				feedDeatil.setReceiveCount(receiveCount.subtract(count).doubleValue());
			}else {
				BigDecimal receiveCount = new BigDecimal(feedDeatil.getProductionUnitReceiveCount().toString());
				BigDecimal count = new BigDecimal(wiodb.getCount().toString());
				feedDeatil.setProductionUnitReceiveCount(receiveCount.subtract(count).doubleValue());
			}
			if(wiodb.getSelfOutFuCount()>0) {
				boolean isFinish = this.checkFeedOrderIsFinish(feedDeatil, wiodb, true, 0);
				if(isFinish) {
					feedDeatil.setIsReceiveFinish(1); 
				}else {
					feedDeatil.setIsReceiveFinish(0); 
				}
			}else {
				feedDeatil.setIsReceiveFinish(0); 
			}
			feedList.add(feedDeatil);
			map.put("feedList", feedList);
			companyMaterialMapper.updateFeedOrderDetailReceive(map);
		}else if(wiodb.getType()==7) {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			map.put("otherId",wiodb.getId());
			map.put("status",2);
			map.put("approvalReason", "仓库退回");
			map.put("time",simpleDateFormat.format(new Date()));
			workshopService.approvalReportByOtherId(map);
		}else if(wiodb.getSource().equals(1)) {
			map.put("otherId", wiodb.getId());
			if(map.get("approvalReason")==null||map.get("approvalReason").toString().equals("")) {
				map.put("approvalReason","出入库退回");
			}
			//审核出入库信息 
			map.put("status",2);
			otherWarehouseMapper.updateOtherWarehouseStatusById(map);
			map.put("name", map.get("loginUserName"));
			workshopService.approvalReportByOtherId(map);
		}
		return null;
	}
	
	//确认出入库单 
	public String confirmWarehouse(WarehouseInOutDetailBean wiodb,Map<String,Object> map) throws CloneNotSupportedException, ParseException {
		
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//出库
		String feedDetailId = null;
		//物料库存
		CompanyMaterialCountBean companyMaterialCountBean = (CompanyMaterialCountBean) map.get("companyMaterialCount");
		//物料信息
		CompanyMaterialTableBean companyMaterialTableBean = (CompanyMaterialTableBean) map.get("cmtb");
		//出入库数量
		BigDecimal count = new BigDecimal(wiodb.getCount().toString());
		//物料单位库存数量
		BigDecimal materialCount = new BigDecimal(companyMaterialCountBean.getCount().toString());
		//生产单位库存数量
		BigDecimal productionUniCount = new BigDecimal(companyMaterialCountBean.getProductionUnitCount().toString());
		//出入库总额
		BigDecimal inOutMoney = new BigDecimal(wiodb.getInOutMoney());
		//库存入库总额
		BigDecimal inSumPrice = new BigDecimal(companyMaterialCountBean.getInSumPrice()==null?"0":companyMaterialCountBean.getInSumPrice().toString());
		//库存存入总数
		BigDecimal inSumCount = new BigDecimal(companyMaterialCountBean.getInSumCount()==null?"0":companyMaterialCountBean.getInSumCount().toString());
		//如果是出库
		if(wiodb.getType()==2 || wiodb.getType()==5 || wiodb.getType()==9 || wiodb.getType()==12) {
			Assert.isTrue(wiodb.getCount()!=null && wiodb.getCount().doubleValue()>0, "出库数不能小于等于0");
			//如果是公司内部出库
			if(wiodb.getType()==2 || wiodb.getType()==5) {
				companyMaterialCountBean.setInSumCount(inSumCount.subtract(count).doubleValue());
				companyMaterialCountBean.setInSumPrice(inSumPrice.subtract(inOutMoney).doubleValue());
				if(companyMaterialCountBean.getInSumCount()<=0 || companyMaterialCountBean.getInSumPrice() <=0) {
					companyMaterialCountBean.setInSumCount(inSumCount.doubleValue());
					companyMaterialCountBean.setInSumPrice(inSumPrice.doubleValue());
				}
				//校验库存，校验两个仓位总库
				this.checkOutMaterial(companyMaterialTableBean, wiodb);
				//出库单位与物料单位一致设置物料库存
				if(wiodb.getInOutUnit().equals(companyMaterialTableBean.getUnit())) {
					//不同仓位数量补足
					companyMaterialCountBean = this.subMaterialCount(companyMaterialCountBean, wiodb, map,1);
				}else {//出库单位与物料单位不一致，出生产单位库存
					companyMaterialCountBean = this.subMaterialCount(companyMaterialCountBean, wiodb, map,2);
				}
				
				if(wiodb.getType()==2) {
					//投料单出库
					feedDetailId = wiodb.getFeedOrder();
					Assert.isTrue(feedDetailId !=null && !feedDetailId.trim().equals(""), "投料单明细id为空异常");
					FeedOrderDetailBean feedOrderDetailBean = orderMapper.getFeedOrderDetailOneById(feedDetailId);
					Assert.notNull(feedOrderDetailBean, "投料单明细为空异常");
					Double feedCount = feedOrderDetailBean.getActualFeedCount();
					Double productionFeedCount = feedOrderDetailBean.getProductionUnitFeedCount();
					Map<String,Object> feedUseCountMap = new HashMap<String,Object>();
					feedUseCountMap.put("feedDetailId", feedOrderDetailBean.getId());
					feedUseCountMap.put("loginCompany", map.get("loginCompany"));
					//查询当前投料单是否有占用
					List<FeedUseMaterialCountBean> feedUseMaterialCountBeans = feedUseMaterialCountMapper.getFeedUseMaterialCountByFeedDetailId(feedUseCountMap);
					if(feedUseMaterialCountBeans!=null && feedUseMaterialCountBeans.size()>0) {
						//当前投料单出库信息(原料仓的)
						//物料单位与出库单位一致的
						if(wiodb.getInOutUnit().equals(companyMaterialTableBean.getUnit())) {
							Assert.isTrue(feedCount.doubleValue()>0, "投料数小于0异常");
							List<WarehouseInOutDetailBean> warehouseInOutDetailBeans =  warehouseMapper.getWarehouseOutDetailByFeed(feedOrderDetailBean);
							BigDecimal materialOutCount = new BigDecimal("0.0");
							if(warehouseInOutDetailBeans!=null && warehouseInOutDetailBeans.size()>0) {
								for(WarehouseInOutDetailBean warehouseInOutDetailBean:warehouseInOutDetailBeans) {
									Assert.notNull(warehouseInOutDetailBean.getCount(), "关联出库数量为空异常");
									materialOutCount = materialOutCount.add(new BigDecimal(warehouseInOutDetailBean.getCount().toString()));
								}
							} 
							/**
							 * 物料单位消占用数   暂时没有用
							 */
							//投料单占用数
							FeedUseMaterialCountBean feedUseMaterialCountBean = feedUseMaterialCountBeans.get(0);
							Double feedUseCount = feedUseMaterialCountBean.getFeedUseCount();
							//投料数-其他仓库出库数-原料仓出库数-当前要出库的数量小于占用数   消占用数
							if(new BigDecimal(feedCount.toString()).subtract(materialOutCount).subtract(new BigDecimal(wiodb.getCount().toString())).subtract(new BigDecimal(feedUseCount.toString())).doubleValue()<0) {
								feedUseMaterialCountBean.setFeedUseCount(new BigDecimal(feedCount.toString()).subtract(materialOutCount).subtract(BigDecimal.valueOf(wiodb.getCount().doubleValue())).doubleValue());
								int feedUseRow = feedUseMaterialCountMapper.updateFeedUseCount(feedUseMaterialCountBean);
								Assert.isTrue(feedUseRow>0, "更新投料单占用数异常");
							}
						}else {
							FeedUseMaterialCountBean feedUseMaterialCountBean = feedUseMaterialCountBeans.get(0);
							Assert.isTrue(productionFeedCount.doubleValue()>0, "投料数小于0异常");
							BigDecimal bigProductionUnitCount = new BigDecimal(feedUseMaterialCountBean.getProductionUnitUseCount().toString());
							feedUseMaterialCountBean.setProductionUnitUseCount(bigProductionUnitCount.subtract(count).doubleValue());
							int feedUseRow = feedUseMaterialCountMapper.updateFeedUseCount(feedUseMaterialCountBean);
							Assert.isTrue(feedUseRow>0, "更新投料单占用数异常");
						}
					} 
					//如果是发料到外协,那么就生成一条外协记录,并且是已审核的
					map.put("feedDetailId",feedDetailId);
					this.addPutOutSourceByIssueNote(wiodb,map);
				}
				
			}else {//出库给客户
				if(wiodb.getWarehouseType().intValue()==1) {//成品出库给客户
					Assert.isTrue(materialCount.subtract(count).doubleValue()>=0, "库存不足");
					companyMaterialCountBean.setCount(materialCount.subtract(count).doubleValue());
				}else if(wiodb.getWarehouseType().intValue()==6) {//半成品出库给客户
					Assert.isTrue(materialCount.subtract(count).doubleValue()>=0, "库存不足");
					companyMaterialCountBean.setCount(materialCount.subtract(count).doubleValue());
				}else {//原材料出库给客户
					//校验库存
					this.checkOutMaterial(companyMaterialTableBean, wiodb);
					companyMaterialCountBean = this.subMaterialCount(companyMaterialCountBean,wiodb,map,1);
				}
			}
			//如果是出库给客户,现金结则自动结算
			if(wiodb.getType() == 9) {
				try {
					companyMaterialService.autoSumMoneyByWarehouseIn(wiodb,map);
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			//库存盘点出库,物料转仓
			if(wiodb.getType()==12 && wiodb.getSourceType() == 6) {
				this.warehouseToOtherWarehouse(wiodb,map,1);
			}
		}else if(wiodb.getType()==7) {//如果是车间交接至仓库
			//如果入库单位和物料单位相同
			if(companyMaterialTableBean.getUnit().equals(wiodb.getInOutUnit())) {
				//物料单位库存数
				companyMaterialCountBean.setCount(materialCount.add(count).doubleValue());
			}else {
				//生产单位库存数
				companyMaterialCountBean.setProductionUnitCount(productionUniCount.add(count).doubleValue());
			}
			map.put("otherId",wiodb.getId());
			map.put("status",1);
			map.put("approvalReason", "仓库确认");
			map.put("time",simpleDateFormat.format(new Date()));
			workshopService.approvalReportByOtherId(map);
		}else if(wiodb.getType()==1 || wiodb.getType()==3) { //采购单入库
			BigDecimal scrapCount = new BigDecimal(wiodb.getScrapCount().toString());
			Map<String,String> purchaseMap = new HashMap<String,String>();
			List<PurchaseOrderBean> purchaseOrderBeanList = new ArrayList<PurchaseOrderBean>();
			purchaseMap.put("purchaseDetailId", wiodb.getPurcharseOrderId());
			purchaseMap.put("loginCompany", map.get("loginCompany").toString());
			PurchaseOrderBean purchaseOrderBean = purchaseOrderMapper.getPurchaseOrderByPurchaseDetailId(purchaseMap);
			Assert.notNull(purchaseOrderBean, "采购单为空异常");
			BigDecimal purchaseInCount = new BigDecimal(purchaseOrderBean.getInCount().toString());
			purchaseOrderBean.setInCount(count.add(purchaseInCount).add(scrapCount).doubleValue());
			purchaseOrderBeanList.add(purchaseOrderBean);
			purchaseOrderMapper.updatePurchaseOrderOnFinish(purchaseOrderBeanList);
			companyMaterialCountBean.setCount(materialCount.add(count).doubleValue());
			companyMaterialCountBean.setInSumCount(inSumCount.add(count).doubleValue());
			companyMaterialCountBean.setInSumPrice(inSumPrice.add(inOutMoney).doubleValue());
			map.put("approvalTime", simpleDateFormat.format(new Date()));
			map.put("approvalUser", map.get("loginUserId"));
			//结算价格
			companyMaterialService.autoSumMoneyByWarehouseIn(wiodb,map);
			//插入仓位
			if(!"".equals(wiodb.getPosition()) && null != wiodb.getPosition()) {
				MaterialPositionBean materialPositionBean = new MaterialPositionBean();
				materialPositionBean.setMaterialCode(wiodb.getMaterialCode());
				materialPositionBean.setPosition(wiodb.getPosition());
				materialPositionBean.setCompany(wiodb.getCompany());
				//添加仓位
				materialPositionService.addMaterialPosition(materialPositionBean);
			}
			if(wiodb.getScrapCount()>0) {
				this.warehouseToOtherWarehouse(wiodb,map,2);
			}
		}else if(wiodb.getType()==4 || wiodb.getType()==8 || wiodb.getType()==11) {//无采购单入库和模板导入入库
			companyMaterialCountBean.setCount(materialCount.add(count).doubleValue());
			//插入仓位
			if(!"".equals(wiodb.getPosition()) && null != wiodb.getPosition()) {
				MaterialPositionBean materialPositionBean = new MaterialPositionBean();
				materialPositionBean.setMaterialCode(wiodb.getMaterialCode());
				materialPositionBean.setPosition(wiodb.getPosition());
				materialPositionBean.setCompany(wiodb.getCompany());
				materialPositionService.addMaterialPosition(materialPositionBean);
			}
			//无采购单入库
			if(wiodb.getType() == 4) {
				companyMaterialCountBean.setInSumCount(inSumCount.add(count).doubleValue());
				companyMaterialCountBean.setInSumPrice(inSumPrice.add(inOutMoney).doubleValue());
				companyMaterialService.autoSumMoneyByWarehouseIn(wiodb,map);
			}
		}else if(wiodb.getSource().equals(1)) {//处理报工交接到仓库
			//出入库不合格数 
			BigDecimal inNoCountBig = new BigDecimal(wiodb.getNoCount().toString());
			//物料单位库存不合格数
			BigDecimal noCountBig = new BigDecimal(companyMaterialCountBean.getNoCount().toString());
			//生产单位库存不合格数
			BigDecimal productionUnitNoCount = new BigDecimal(companyMaterialCountBean.getProductionUnitNoCount().toString());
			//成品仓
			if(wiodb.getWarehouseType().equals(1)) {
				companyMaterialCountBean.setCount(materialCount.add(count).doubleValue());
				companyMaterialCountBean.setNoCount(noCountBig.add(inNoCountBig).doubleValue());
			}else {
				//其他仓位
				if(companyMaterialTableBean.getUnit().equals(wiodb.getInOutUnit())) {
					//物料单位库存数
					companyMaterialCountBean.setCount(materialCount.add(count).doubleValue());
					companyMaterialCountBean.setNoCount(noCountBig.add(inNoCountBig).doubleValue());
				}else {
					//生产单位库存数
					companyMaterialCountBean.setProductionUnitCount(productionUniCount.add(count).doubleValue());
					companyMaterialCountBean.setProductionUnitNoCount(productionUnitNoCount.add(inNoCountBig).doubleValue());
				}
			}
			map.put("otherId",wiodb.getId());
			map.put("status",1);
			map.put("approvalReason","出入库审核");
			map.put("name", map.get("loginUserName"));
			map.put("time", simpleDateFormat.format(new Date()));
			workshopService.approvalReportByOtherId(map);	
		} 
		companyMaterialCountService.updateCompanyMaterialCountOnCountByMaterialCodeAndWarehouseType(companyMaterialCountBean);
		String retrunMsg= this.toReport(feedDetailId,wiodb,map);
		return retrunMsg;  
	}
	
	/**
	 * 审核转仓
	 * @param wiodb
	 * @param map
	 * type 1物料转仓  2入库报废
	 * @throws CloneNotSupportedException 
	 */
	private void warehouseToOtherWarehouse(WarehouseInOutDetailBean wiodb, Map<String, Object> map,int  relationType ) throws CloneNotSupportedException {
		WarehouseInOutDetailBean warehouseInOutDetailBean=(WarehouseInOutDetailBean) wiodb.clone();
		int warehouseType=warehouseInOutDetailBean.getRalationWarehouse();
		int type=11;
		int ralationWarehouse = warehouseInOutDetailBean.getWarehouseType();
		Double  count=warehouseInOutDetailBean.getCount();
		if(2==relationType) {
			warehouseType=2;//报废仓
			type=wiodb.getType();
			ralationWarehouse=-1;
			count=warehouseInOutDetailBean.getScrapCount();
			warehouseInOutDetailBean.setSumMoneyCount(0.0);
			warehouseInOutDetailBean.setInOutMoney(0.0);
		}
		warehouseInOutDetailBean.setType(type);//改为入库
		warehouseInOutDetailBean.setOtherId(wiodb.getId());
		warehouseInOutDetailBean.setId(CreateIdUtil.getId(CreateIdUtil.WAREHOUSE_IN));
		warehouseInOutDetailBean.setStatus(1);
		warehouseInOutDetailBean.setRalationWarehouse(ralationWarehouse);//关联仓库问出库仓库
		warehouseInOutDetailBean.setWarehouseType(warehouseType);//入库仓库为关联仓库
		warehouseInOutDetailBean.setCount(count);
		List<WarehouseInOutDetailBean> warehouseInOutDetailBeans=new ArrayList<WarehouseInOutDetailBean>();
		warehouseInOutDetailBeans.add(warehouseInOutDetailBean);
		//获取仓库库存信息   和出入库信息同一个仓位的库存数
		Map<String,Object> paramMap=new HashMap<String,Object>();
		paramMap.put("loginCompany", map.get("loginCompany"));
		paramMap.put("warehouseType", warehouseInOutDetailBean.getWarehouseType());
		paramMap.put("materialCode", warehouseInOutDetailBean.getMaterialCode());
		List<CompanyMaterialCountBean> companyMaterialCountBeans = companyMaterialCountService.getCompanyMaterialCountListByDetail(paramMap);
		Assert.isTrue((null==companyMaterialCountBeans?0:companyMaterialCountBeans.size())<2, "多条库存信息异常");
		if(companyMaterialCountBeans==null || companyMaterialCountBeans.size()<1) {//如果没有库存记录,增加一个库存记录
			CompanyMaterialCountBean companyMaterialCountBean = new CompanyMaterialCountBean();
			companyMaterialCountBean.setCount(count);
			companyMaterialCountBean.setNoCount(0.0);
			companyMaterialCountBean.setProductionUnitCount(0.0);
			companyMaterialCountBean.setProductionUnitNoCount(0.0);
			//除了成品仓，其他仓位不需要单号
			if(warehouseInOutDetailBean.getWarehouseType().intValue() == 1) {
				companyMaterialCountBean.setOrderId(warehouseInOutDetailBean.getOrderId());
				companyMaterialCountBean.setRowIndex(Integer.valueOf(warehouseInOutDetailBean.getRowIndex()));
			}
			companyMaterialCountBean.setCompany(map.get("loginCompany").toString());
			companyMaterialCountBean.setWarehouseType(warehouseInOutDetailBean.getWarehouseType());
			companyMaterialCountBean.setMaterialCode(warehouseInOutDetailBean.getMaterialCode());
			companyMaterialCountService.addCompanyMaterialCount(companyMaterialCountBean);
		}else {
			CompanyMaterialCountBean companyMaterialCountBean = companyMaterialCountBeans.get(0);
			//物料单位库存数量
			BigDecimal materialCount = new BigDecimal(companyMaterialCountBean.getCount().toString());
			BigDecimal countt = new BigDecimal(count.toString());
			companyMaterialCountBean.setCount(materialCount.add(countt).doubleValue());
			companyMaterialCountService.updateCompanyMaterialCountOnCountByMaterialCodeAndWarehouseType(companyMaterialCountBean);
		}
		int row=companyMaterialMapper.insertInOutRecode(warehouseInOutDetailBeans);
	}




	/**
	 * 删除出入库单
	 * @date 2018年9月18日 下午5:01:17 
	 * @author 李斌
	 * @return void 
	 * @throws
	 */
	public void deleteWarehouse(Map<String, String> map) {
		Map<String,Object> paramMap = new HashMap<String,Object>();
		WarehouseInOutDetailBean wiodb=companyMaterialMapper.getInWarehourseByIdOne(map.get("id").toString());
		Assert.isTrue(wiodb!=null, "该出入库单已删除");
		Assert.isTrue(wiodb.getStatus()==0, "该出入库单已经审核,无法删除");
		if(wiodb.getType()==1 || wiodb.getType()==3) {
			List<PurchaseOrderBean> purchaseOrderBeanList = new ArrayList<PurchaseOrderBean>();
			map.put("purchaseDetailId", wiodb.getPurcharseOrderId());
			map.put("loginCompany", map.get("loginCompany").toString());
			PurchaseOrderBean purchaseOrderBean = purchaseOrderMapper.getPurchaseOrderByPurchaseDetailId(map);
			Assert.notNull(purchaseOrderBean, "采购单为空异常");
			purchaseOrderBean.setIsFinish(0);
			purchaseOrderBeanList.add(purchaseOrderBean);
			purchaseOrderMapper.updatePurchaseOrderOnFinish(purchaseOrderBeanList);
		}else if(wiodb.getType()==2) {
			List<FeedOrderDetailBean> feedList=new ArrayList<FeedOrderDetailBean>();
			FeedOrderDetailBean feedDeatil=orderService.getFeedOrderDetailOneById(wiodb.getFeedOrder());
			paramMap.put("materialCode", wiodb.getMaterialCode());
			paramMap.put("loginCompany", map.get("loginCompany"));
			CompanyMaterialTableBean cmtb=companyMaterialMapper.getCompanyMaterialTableByMaterialCode(paramMap);
			Assert.notNull(cmtb, "物料信息为空");
			//出入库单位和库存单位相同
			if(wiodb.getInOutUnit().equals(cmtb.getUnit())) {
				//物料单位领料数
				BigDecimal bigFeedReceiveCount = new BigDecimal(feedDeatil.getReceiveCount().toString());
				//物料单位出库数
				BigDecimal bigOutCount = new BigDecimal(wiodb.getCount().toString());
				feedDeatil.setReceiveCount(bigFeedReceiveCount.subtract(bigOutCount).doubleValue());
				feedDeatil.setIsReceiveFinish(0);
			}else {
				//生产单位领料数
				BigDecimal bigFeedReceiveCount = new BigDecimal(feedDeatil.getProductionUnitReceiveCount().toString());
				//生产单位出库数
				BigDecimal bigOutCount = new BigDecimal(wiodb.getCount().toString());
				feedDeatil.setProductionUnitReceiveCount(bigFeedReceiveCount.subtract(bigOutCount).doubleValue());
				feedDeatil.setIsReceiveFinish(0);
			}
			if(wiodb.getSelfOutFuCount()>0) {
				boolean isFinish = this.checkFeedOrderIsFinish(feedDeatil, wiodb, true, 0);
				if(isFinish) {
					feedDeatil.setIsReceiveFinish(1);
				}
			}
			feedList.add(feedDeatil);
		    //修改投料单明细的领料数
		    paramMap.put("feedList", feedList);
		    companyMaterialMapper.updateFeedOrderDetailReceive(paramMap);
		}else if(wiodb.getType()==7) {
			workshopService.deleteReportByOtherId(wiodb.getId());
		}else if(wiodb.getSource().equals(1)) {
			//报工
			workshopService.deleteReportByOtherId(wiodb.getId());
		}
		int row = warehouseMapper.deleteWarehouse(wiodb);
		Assert.isTrue(row>0, "删除出入库失败");
	}
	
	/**
	 * 扣除库存(消减原料仓和辅料仓库存)
	* @date 2018年9月28日 上午11:10:05 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public CompanyMaterialCountBean subMaterialCount(CompanyMaterialCountBean companyMaterialCountBean,WarehouseInOutDetailBean wiodb,Map<String, Object> map,int unitType) {
		BigDecimal count = new BigDecimal(wiodb.getCount().toString());
		//物料单位库存
		BigDecimal materialCount = new BigDecimal(companyMaterialCountBean.getCount().toString());
		//生产单位库存
		BigDecimal productionUniCount = new BigDecimal(companyMaterialCountBean.getProductionUnitCount().toString());
		
		if(unitType==1) {//出库单位和物料单位相同
			//如果同仓位的库存数小于出库数
			if(materialCount.subtract(count).doubleValue()<0) {
				if(wiodb.getWarehouseType().intValue()==4) {
					map.put("warehouseType", 5);
				}else {
					map.put("warehouseType", 4);
				}
				map.put("materialCode", companyMaterialCountBean.getMaterialCode());
				//查询不同仓位的库存数
				List<CompanyMaterialCountBean> companyMaterialCountBeans = companyMaterialCountService.getCompanyMaterialCountListByDetail(map);
				//辅料
				CompanyMaterialCountBean auxiliaryMaterial = companyMaterialCountBeans.get(0);
				BigDecimal auxiliaryMaterialCount = new BigDecimal(auxiliaryMaterial.getCount().toString());
				if(auxiliaryMaterialCount.subtract(count).doubleValue()>0) {
					companyMaterialCountBean = companyMaterialCountBeans.get(0);
					companyMaterialCountBean.setCount(auxiliaryMaterialCount.subtract(count).doubleValue());
				}else {
					//先减辅料仓的库存 剩下的交给原料仓来减
					BigDecimal surplusOutCount =  count.subtract(auxiliaryMaterialCount);
					//辅料仓库存为0
					auxiliaryMaterial.setCount(0.0);
					//减原料仓
					companyMaterialCountBean.setCount(materialCount.subtract(surplusOutCount).doubleValue());
				}
				//更新辅料仓
				companyMaterialCountService.updateCompanyMaterialCountOnCountByMaterialCodeAndWarehouseType(auxiliaryMaterial);
			}else {//如果同仓位库存数大于等于，将库存数减去出库数
				companyMaterialCountBean.setCount(materialCount.subtract(count).doubleValue()); 
			}
		}else {  //物料单位和生产单位不相同
			//原材料不足,辅料顶
			if(productionUniCount.subtract(count).doubleValue()<0) {
				if(wiodb.getWarehouseType().intValue()==4) {
					map.put("warehouseType", 5);
				}else {
					map.put("warehouseType", 4);
				}
				map.put("materialCode", companyMaterialCountBean.getMaterialCode());
				List<CompanyMaterialCountBean> companyMaterialCountBeans = companyMaterialCountService.getCompanyMaterialCountListByDetail(map);
				//辅料
				CompanyMaterialCountBean auxiliaryMaterial = companyMaterialCountBeans.get(0);
				BigDecimal auxiliaryMaterialProductionCount = new BigDecimal(auxiliaryMaterial.getProductionUnitCount().toString());
				if(auxiliaryMaterialProductionCount.subtract(count).doubleValue()>0) {
					companyMaterialCountBean = companyMaterialCountBeans.get(0);
					companyMaterialCountBean.setProductionUnitCount(auxiliaryMaterialProductionCount.subtract(count).doubleValue());
				}else {
					//先减辅料仓的库存 剩下的交给原料仓来减
					BigDecimal surplusOutCount =  count.subtract(auxiliaryMaterialProductionCount);
					//辅料仓库存为0
					auxiliaryMaterial.setProductionUnitCount(0.0);
					//减原料仓
					companyMaterialCountBean.setProductionUnitCount(productionUniCount.subtract(surplusOutCount).doubleValue());
				}
				//更新辅料仓
				companyMaterialCountService.updateCompanyMaterialCountOnCountByMaterialCodeAndWarehouseType(auxiliaryMaterial);
			}else {
				companyMaterialCountBean.setProductionUnitCount(productionUniCount.subtract(count).doubleValue()); 
			}
		}
		return companyMaterialCountBean;
	}
	
  
	/**
	 * 校验物料
	* @date 2018年9月13日 下午1:41:08 
	* @author 李斌
	* @return int 
	* @throws
	 */
	public void isCheckMateiral(CompanyMaterialTableBean companyMaterialTableBean,String message) {
		Assert.notNull(companyMaterialTableBean,"物料信息为空异常");
		Assert.isTrue(!"禁用".equals(companyMaterialTableBean.getStatus()),"该物料被禁用,"+message);
//		Assert.isTrue("原材料仓".equals(companyMaterialTableBean.getDefaultWarehouse()) || "辅料仓".equals(companyMaterialTableBean.getDefaultWarehouse()),"该物料非原材料仓与辅料仓,"+message);
	}
	
	/**
	 * 交接入库
	* @date 2018年9月17日 上午11:24:16 
	* @author 李斌
	* @return String 
	* @throws
	 */
	public String toReport(String feedDetailId,WarehouseInOutDetailBean wiodb,Map<String,Object> map) throws CloneNotSupportedException {
		String isTry = map.get("isTcy")==null?"":map.get("isTcy").toString();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		if( wiodb.getType() == 2 && (wiodb.getSource() ==null || wiodb.getSource().intValue()!=2) && !isTry.equals("2")) {
			map.put("feedDetailId", feedDetailId);
			FeedOrderDetailBean feedOrderDetailBean = orderMapper.getFeedOrderDetailOneById(feedDetailId);
			Assert.notNull(feedOrderDetailBean, "投料单明细为空异常");
			if(feedOrderDetailBean.getType()==2) {
				ApplyRepairFormBean applyRepairFormBean = applyRepairFormMapper.getApplyByFeedDetailId(map);
				if(applyRepairFormBean==null) {
					throw new ServiceException("申补投料单明细为空异常");
				}  
				/*if(applyRepairFormBean.getType()==1) {
					return "损耗的申补单无需交接车间"; 
				}*/
			} 
			MyUser myUser = new MyUser();
			myUser.setCompany(map.get("loginCompany").toString());
			myUser.setUserId(map.get("loginUserId").toString());
			myUser.setUserName(map.get("loginUserName").toString());
			String reportJSONStr =  companyMaterialService.getReportDataByWarehouse(wiodb,myUser,simpleDateFormat.format(new Date()));
			if(!isTry.equals("1")) {
				try { 
					workshopService.insertReport(reportJSONStr, wiodb.getCreateUser(), myUser);
				} catch (ServiceException e) {
					if(e.getMessage().indexOf("车间最多还可入库或领料")>0 || e.getMessage().equals("合格数加不合格数必须大于0")) { //如果异常中有这五个字
						//手动回滚
						TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
						return "重新确认"; 
					}else {
						throw e;
					}
				} 
			}else {
				try { 
					workshopService.insertReport(reportJSONStr, wiodb.getCreateUser(), myUser);
				} catch (ServiceException e) {
					if(e.getMessage().equals("合格数加不合格数必须大于0")){
						throw new ServiceException("出库数量异常,仓库交接到车间,物料转换为付时,交接数量小于1");
					}else {
						throw e;
					}
				} 
			}
		}
		return null;
	}
	/**
	 * 库存不足警报
	* @date 2018年9月17日 下午1:18:27 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public void sendUunderStockMessage(WarehouseInOutDetailBean wiodb,CompanyMaterialCountBean companyMaterialCountBean,CompanyMaterialTableBean companyMaterialTableBean,String date,Map<String,Object> map) {
		if((wiodb.getType()==2 || wiodb.getType()==5 || (wiodb.getType()==9  && wiodb.getWarehouseType().intValue() != 1) ) && wiodb.getStatus() == 1) {
			if(companyMaterialCountBean.getCount()<companyMaterialTableBean.getSafetyStockMin()) {
				String title = "库存不足报警";
				String bodyMessage = "物料名称-"+companyMaterialTableBean.getMaterialName()+" 物料规格-"+(companyMaterialTableBean.getModel()==null?"":companyMaterialTableBean.getModel())+" 色号-"+(companyMaterialTableBean.getColor()==null?"":companyMaterialTableBean.getColor())+" 供应商-"+companyMaterialTableBean.getProviderName()+" ---目前库存数:"+companyMaterialCountBean.getCount();
				companyMaterialService.sendSafetyStockMinMessage(title, bodyMessage, date, map, RedirectUrlUtil.queryStock,"8",0);
			}
		} 
	}
	
	/**
	 * 修改出入库
	* @date 2018年9月19日 上午8:52:44 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public void updateWarehouse(Map<String, String> map) {
		//修改数
		BigDecimal bigCount = new BigDecimal(map.get("count").toString());
		WarehouseInOutDetailBean wiodb=companyMaterialMapper.getInWarehourseByIdOne(map.get("id").toString());
		Assert.isTrue(wiodb!=null, "该出入库单已被删除,修改失败");
		Assert.isTrue(wiodb.getStatus()==0, "该出入库单已审核,不能修改");
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("materialCode", wiodb.getMaterialCode());
		paramMap.put("loginCompany", map.get("loginCompany"));
		CompanyMaterialTableBean cmtb=companyMaterialMapper.getCompanyMaterialTableByMaterialCode(paramMap);
		CompanyMaterialCountBean companyMaterialCountBean = null;
		if(wiodb.getWarehouseType().intValue()!=1) {
			companyMaterialCountBean = companyMaterialCountService.getCompanyMaterialCountByMaterial(paramMap);
			Assert.notNull(cmtb, "物料信息为空异常");
		}else {
			paramMap.put("orderId",wiodb.getOrderId());
			paramMap.put("rowIndex",wiodb.getRowIndex());
			List<CompanyMaterialCountBean> companyMaterialCountBeans = companyMaterialCountService.getCompanyMaterialCountListByDetail(paramMap);
			Assert.isTrue(companyMaterialCountBeans !=null && companyMaterialCountBeans.size()==1, "库存信息异常");
			companyMaterialCountBean = companyMaterialCountBeans.get(0);
		}
		Assert.notNull(companyMaterialCountBean, "库存信息为空异常");
		if(wiodb.getType()==1 || wiodb.getType()==3) {
			Map<String,String> purchaseMap = new HashMap<String,String>();
			List<PurchaseOrderBean> purchaseOrderBeanList = new ArrayList<PurchaseOrderBean>();
			purchaseMap.put("purchaseDetailId", wiodb.getPurcharseOrderId());
			purchaseMap.put("loginCompany", map.get("loginCompany").toString());
			PurchaseOrderBean purchaseOrderBean = purchaseOrderMapper.getPurchaseOrderByPurchaseDetailId(purchaseMap);
			Assert.notNull(purchaseOrderBean, "采购单为空异常");
			purchaseOrderBean.setStatus(0);
			BigDecimal purchaseInCount = new BigDecimal("0.0");
			BigDecimal purchaseCount = new BigDecimal(purchaseOrderBean.getPurchaseCount().toString());
			//上次入库数
			BigDecimal bigOldInCount = new BigDecimal(wiodb.getCount().toString());
			List<WarehouseInOutDetailBean> allInCountData = warehouseMapper.getWarehouseInByPurchaseDetail(purchaseOrderBean);
			for(WarehouseInOutDetailBean ware:allInCountData) {
				purchaseInCount = purchaseInCount.add(new BigDecimal(ware.getCount().toString()));
			}
			//入库允许修改数
			BigDecimal bigAllowUpdateCount = purchaseCount.subtract(purchaseInCount).add(bigOldInCount);
			if(bigCount.subtract(bigAllowUpdateCount).doubleValue()>0) {//如果修改数大于允许修改数
				throw new ServiceException("最大修改数为"+bigAllowUpdateCount.doubleValue());
			}else if(bigCount.subtract(bigAllowUpdateCount).doubleValue()==0){
				purchaseOrderBean.setIsFinish(1);
			}else {
				purchaseOrderBean.setIsFinish(0);
			}
			purchaseOrderBeanList.add(purchaseOrderBean);
			purchaseOrderMapper.updatePurchaseOrderOnFinish(purchaseOrderBeanList);
		}else if(wiodb.getType()==2) {
			//通过出库数据查找投料单明细
			List<FeedOrderDetailBean> feedList=new ArrayList<FeedOrderDetailBean>();
			FeedOrderDetailBean feedDeatil=orderService.getFeedOrderDetailOneById(wiodb.getFeedOrder());
			//如果出库记录中的单位和物料单位一致,说明是物料单位出库
			if(cmtb.getUnit().equals(wiodb.getInOutUnit())) {
				//物料单位投料数
				BigDecimal bigFeedCount = new BigDecimal(feedDeatil.getFeedCount().toString());
				//物料单位投料单可领数
				BigDecimal bigReceiveCount = new BigDecimal(feedDeatil.getReceiveCount().toString());
				//物料单位上次出库数
				BigDecimal bigOldOutCount = new BigDecimal(wiodb.getCount().toString());
				//物料单位最大可领数
				BigDecimal bigAllowUpdateCount = bigFeedCount.subtract(bigReceiveCount).add(bigOldOutCount);
				//库存数量
				BigDecimal bigMaterialCount = new BigDecimal("0.0");
				if(companyMaterialCountBean.getCount()!=null) {
					bigMaterialCount = new BigDecimal(companyMaterialCountBean.getCount().toString());
				} 
				if(bigMaterialCount.subtract(bigCount).doubleValue()<0) { 
					throw new ServiceException("库存不足,剩余可修改数为:"+bigMaterialCount);
				}
				if(bigCount.subtract(bigAllowUpdateCount).doubleValue()>0) {//如果修改数大于允许修改数
					throw new ServiceException("最大修改数为"+bigAllowUpdateCount.doubleValue());
				}
				feedDeatil.setReceiveCount(bigReceiveCount.subtract(bigOldOutCount).add(bigCount).doubleValue());
			}else {//生产单位出库
				//生产单位投料数
				BigDecimal bigFeedCount = new BigDecimal(feedDeatil.getProductionUnitFeedCount().toString());
				//生产单位投料单可领数
				BigDecimal bigReceiveCount = new BigDecimal(feedDeatil.getProductionUnitReceiveCount().toString());
				//生产单位上次出库数
				BigDecimal bigOldOutCount = new BigDecimal(wiodb.getCount().toString());
				//生产单位最大可领数
				BigDecimal bigAllowUpdateCount = bigFeedCount.subtract(bigReceiveCount).add(bigOldOutCount);
				//库存数量
				BigDecimal bigMaterialCount = new BigDecimal("0.0");
				if(companyMaterialCountBean.getProductionUnitCount()!=null) {
					bigMaterialCount = new BigDecimal(companyMaterialCountBean.getProductionUnitCount().toString());
				} 
				if(bigMaterialCount.subtract(bigCount).doubleValue()<0) {
					throw new ServiceException("库存不足,剩余可修改数为:"+bigMaterialCount);
				}
				if(bigCount.subtract(bigAllowUpdateCount).doubleValue()>0) {//如果修改数大于允许修改数
					throw new ServiceException("最大修改数为"+bigAllowUpdateCount.doubleValue());
				} 
				feedDeatil.setProductionUnitReceiveCount(bigReceiveCount.subtract(bigOldOutCount).add(bigCount).doubleValue());
			}
			//物料单位出库数
			BigDecimal oldReceiveCount = new BigDecimal(feedDeatil.getReceiveCount().toString());
			//生产单位出库数
			BigDecimal oldProductionUnitReceiveCount = new BigDecimal(feedDeatil.getProductionUnitReceiveCount().toString());
			//物料单位投料数
			BigDecimal oldFeedCount = new BigDecimal(feedDeatil.getFeedCount().toString());
			//生产单位投料数
			BigDecimal oldProductionFeedCount = new BigDecimal(feedDeatil.getProductionUnitFeedCount().toString());
			//原状态
			int oldIsFinish = feedDeatil.getIsReceiveFinish();
			if(oldReceiveCount.subtract(oldFeedCount).doubleValue()==0 && oldProductionUnitReceiveCount.subtract(oldProductionFeedCount).doubleValue()==0) {
				feedDeatil.setIsReceiveFinish(1);
			}else { 
				feedDeatil.setIsReceiveFinish(0);
			}
			//原交接数
			int updateBeforeSelfOutCount = 0;
			if(wiodb.getSelfOutFuCount()>0) {
				updateBeforeSelfOutCount = wiodb.getSelfOutFuCount();
			}else {
				updateBeforeSelfOutCount = wiodb.getCount().intValue();
			}
			//修改后的交接数
			int updateAfterSelfOutCount = 0;
			if(map.get("selfOutFuCount")==null) {
				updateAfterSelfOutCount = Integer.parseInt(map.get("count"));
			}else {
				updateAfterSelfOutCount = Integer.parseInt(map.get("selfOutFuCount"));
				Assert.isTrue(updateAfterSelfOutCount>0, "交接数量不能改为0");
			}
			boolean isFinish = this.checkFeedOrderIsFinish(feedDeatil, wiodb,true,updateAfterSelfOutCount);
			if(isFinish) {
				feedDeatil.setIsReceiveFinish(1);
			}
			//现状态
			int newIsFinish = feedDeatil.getIsReceiveFinish();
			//原先领料完成了.现在按物料算,领料没完成,那么就做处理
			if(oldIsFinish==1 && newIsFinish==0) {
				//前提是用户能写交接数量,能写的前提是单位不相同,也就是物料单位不为付
				if(!"付".equals(cmtb.getUnit())) {
					//如果用户修改了交接数量
					if(updateAfterSelfOutCount != updateBeforeSelfOutCount) {
						//如果交接数量减小了.那么就设置为未完成
						if(updateAfterSelfOutCount<updateBeforeSelfOutCount) {
							isFinish = this.checkFeedOrderIsFinish(feedDeatil, wiodb,true,updateAfterSelfOutCount);
							if(isFinish) {
								feedDeatil.setIsReceiveFinish(1);
							}
						}else if(updateAfterSelfOutCount>updateBeforeSelfOutCount) {
							feedDeatil.setIsReceiveFinish(1);
						}
					}else {
						//如果用户没有修改交接入库数,而是修改了出库数,那么依旧不能再次领料
						feedDeatil.setIsReceiveFinish(1);
					}
				}
			}
			//当用户填写了交接数才能更新
			if(map.get("selfOutFuCount")!=null) {
				wiodb.setSelfOutFuCount(updateAfterSelfOutCount);
			}
			feedList.add(feedDeatil); 
		    //修改投料单明细的领料数 
		    paramMap.put("feedList", feedList);
		    companyMaterialMapper.updateFeedOrderDetailReceive(paramMap);
		}else if(wiodb.getType()==5 || wiodb.getType()==9) {
			if(wiodb.getWarehouseType().intValue()!=1) {
				//原出库数
				BigDecimal oldCount = new BigDecimal(wiodb.getCount().toString());
				//库存数量
				BigDecimal materialReceiveCount =new BigDecimal("0.0");
				//采购数
				BigDecimal purchaseCount = new BigDecimal("0.0");
				//排除订单的库存数
				BigDecimal notOrderMaterialCount = new BigDecimal("0.0");
				//所有投料数
				BigDecimal allFeedCount = new BigDecimal("0.0");
				Map<String, Double> mapCount =  otherWarehouseMapper.getCountResult(wiodb.getMaterialCode(),map.get("loginCompany").toString());
				if(mapCount.get("purchaseCount")!=null) {
					purchaseCount = new BigDecimal(mapCount.get("purchaseCount").toString());
				}
				if(mapCount.get("feedCount")!=null) {
					allFeedCount = new BigDecimal(mapCount.get("feedCount").toString());
				}
				if(mapCount.get("stockCount")!=null) {
					notOrderMaterialCount = new BigDecimal(mapCount.get("stockCount").toString());
				} 
				//可领取库存数
				materialReceiveCount = purchaseCount.add(notOrderMaterialCount).subtract(allFeedCount).add(oldCount);
				if(materialReceiveCount.subtract(bigCount).doubleValue()<0) {
					throw new ServiceException("库存不足或该物料数量被投料单占用,最大可修改数为"+materialReceiveCount);
				}
			}else {
				//成品库存
				long materialCount = companyMaterialCountBean.getCount().longValue();
				//原出库数
				long oldOutCount = wiodb.getCount().longValue();
				Map<String,Object> finishMap = new HashMap<String,Object>();
				//获取本订单本行的订单数
				finishMap.put("orderId", wiodb.getOrderId());
				finishMap.put("rowIndexs", wiodb.getRowIndex());
				finishMap.put("otherOrderId", wiodb.getOrderId());
				finishMap.put("loginCompany", map.get("loginCompany"));
				//本行订单投料数
				long orderRowCount=otherWarehouseMapper.getOrderRowCount(finishMap);
				//成品剩余库存可用数
				long residueCount =  otherWarehouseMapper.getOrderStockRowCount(finishMap);
				Assert.isTrue(residueCount+oldOutCount>=bigCount.longValue(),"库存不足,有效库存数为："+materialCount);
				//获取本订单本行已经出库数,不分审核还是未审核
				finishMap.put("status", 7);  
				long orderRowAleradyOutCount=otherWarehouseMapper.orderRowAleradyOutCount(map);
				Assert.isTrue(orderRowAleradyOutCount+bigCount.longValue()-oldOutCount<=orderRowCount,"本订单或其他订单已出库和为："+orderRowAleradyOutCount+",最大修改数为"+(orderRowCount-orderRowAleradyOutCount-oldOutCount));
			} 
		}else if(wiodb.getType()==7 || wiodb.getSource().intValue()==1) {
			throw new ServiceException("请至我的报工页面修改！");
		}
		wiodb.setStatus(0);//修改状态为未审批
		wiodb.setCount(bigCount.doubleValue());//设置数量
		
		this.updateWarehouseInOutCount(wiodb);
	}
	
	/**
	 * 修改合格数不合格数
	 * @param wiodb
	 */
	public void updateWarehouseInOutCount(WarehouseInOutDetailBean wiodb) {
		int row = warehouseMapper.updateWarehouseInOutCount(wiodb); 
		Assert.isTrue(row>0, "修改出入库数量失败");
	}

	/**
	 * 获取出入库记录
	* @date 2018年9月19日 下午1:53:12 
	* @author 李斌
	* @return DatatablesViewPageBean<WarehouseInOutDetailBean> 
	* @throws
	 */
	public DatatablesViewPageBean<WarehouseInOutDetailBean> getWarehouseInOutDetaliList(Map<String, Object> map) {
		DatatablesViewPageBean<WarehouseInOutDetailBean> datatablesViewPageBean = new DatatablesViewPageBean<WarehouseInOutDetailBean>();
		List<WarehouseInOutDetailBean> warehouseInOutDetailList = warehouseMapper.getWarehouseInOutDetailData(map);
		this.checkWarehouseApprovalPermission(map,warehouseInOutDetailList);
		int count = warehouseMapper.getWarehouseInOutDetailCount(map);
		datatablesViewPageBean.setiTotalDisplayRecords(count);
		datatablesViewPageBean.setiTotalRecords(count);
		datatablesViewPageBean.setReturnData(warehouseInOutDetailList);
		return datatablesViewPageBean;
	}
	
	/**
	 * 获取出入库总价
	 * @param map
	 * @return
	 */
	public Map getInOutSumPrice(Map map) {
		return  warehouseMapper.getInOutSumPrice(map);
	}
	
	
	
	
	/**
	 * 校验出入库记录的权限
	 * @param map
	 * @param warehouseInOutDetailList
	 */
	private void checkWarehouseApprovalPermission(Map map,List<WarehouseInOutDetailBean> warehouseInOutDetailList) {
		//判断审核权限
		Map<String, Object> approvalParam = new HashMap<String,Object>();
		approvalParam.put("type","6"); 
		approvalParam.put("loginUserId", map.get("loginUserId"));
		approvalParam.put("loginCompany", map.get("loginCompany"));
		List<String> userIds = approvalService.getApprovalIdByLoginId(approvalParam);
		userIds=userIds==null?new ArrayList<String>():userIds;
		approvalParam.put("type","12"); 
		List<String> stockUserId = approvalService.getApprovalIdByLoginId(approvalParam);
		stockUserId=stockUserId==null?new ArrayList<String>():stockUserId;
		int isAotoApproval = compangMapper.getIsAutoApprovalByCompany(map);
		//判断当前登录人可审核的单子 
		for(WarehouseInOutDetailBean wod:warehouseInOutDetailList) {
			//如果是库存盘点
			if(wod.getSourceType()==5) {
				//如果可审核人包含制单人
				if(stockUserId.contains(wod.getCreateUserId())) {
					wod.setIsApperval(1);
				}
				if(wod.getStatus()==0) {
					approvalParam.put("loginUserId", wod.getCreateUserId());
					approvalParam.put("type","12"); 
					List<String> approvalUserList = approvalMapper.getApprovalUserBeanByLoginUserId(approvalParam);
					wod.setAuditableUser(approvalUserList);
				}
			}else {
				//如果可审核人包含制单人
				if(userIds.contains(wod.getCreateUserId())) {
					wod.setIsApperval(1);
				}
				if(wod.getStatus()==0) {
					approvalParam.put("loginUserId", wod.getCreateUserId());
					approvalParam.put("type","6"); 
					List<String> approvalUserList = approvalMapper.getApprovalUserBeanByLoginUserId(approvalParam);
					wod.setAuditableUser(approvalUserList);
				}
			}
		}
	}




	/**
	 * 获取发送消息的记录
	* @date 2018年9月19日 下午2:14:15 
	* @author 李斌
	* @return DatatablesViewPageBean<WarehouseInOutDetailBean> 
	* @throws
	 */
	public DatatablesViewPageBean<WarehouseInOutDetailBean> getWarehouseInOutDetailByIds(Map<String,Object> map){
		Assert.notNull(map.get("ids"), "参数不全异常 ids为空");
		String ids = map.get("ids").toString();
		map.put("ids",ids.split(","));
		return this.getWarehouseInOutDetaliList(map);
	}

	/**
	 * 获取出入库制单人
	* @date 2018年9月19日 下午4:03:37 
	* @author 李斌
	* @return List<UserBean> 
	* @throws
	 */
	public List<UserBean> getWarehouseInOutCreateUser(Map<String, Object> map) {
		return warehouseMapper.getWarehouseInOutCreateUser(map);
	}

	/**
	 * 获取出入库所有的客户
	* @date 2018年9月19日 下午4:10:13 
	* @author 李斌
	* @return List<String> 
	* @throws
	 */
	public List<UserBean> getCustomerNameByWarehouse(Map<String, Object> map) {
		return warehouseMapper.getCustomerNameByWarehouse(map);
	}

	/**
	 * 获取出入库汇总
	* @date 2018年9月20日 上午8:35:26 
	* @author 李斌
	* @return DatatablesViewPageBean<WarehouseInOutDetailBean> 
	* @throws
	 */
	public DatatablesViewPageBean<WarehouseInOutDetailBean> getInOutSummary(Map<String, Object> map) {
		List<WarehouseInOutDetailBean> warehouseInOutDetailList = warehouseMapper.getInOutSummaryData(map);
		int count = warehouseMapper.getInOutSummaryCount(map);
		DatatablesViewPageBean<WarehouseInOutDetailBean> datatablesViewPageBean = new DatatablesViewPageBean<WarehouseInOutDetailBean>();
		datatablesViewPageBean.setiTotalDisplayRecords(count);
		datatablesViewPageBean.setiTotalRecords(count);
		datatablesViewPageBean.setReturnData(warehouseInOutDetailList);
		return datatablesViewPageBean;
	}
	
	/**
	 * 根据库存信息获取出入库
	* @date 2018年9月20日 上午11:09:15 
	* @author 李斌
	* @return List<WarehouseInOutDetailBean> 
	* @throws
	 */
	public List<WarehouseInOutDetailBean> getWarehouseInOutDetaliListByMaterial(Map<String, Object> map) {
		return warehouseMapper.getWarehouseInOutDetaliListByMaterial(map);
	}

	/**
	 * 获取投料单领料+物料领料数据
	* @date 2018年9月20日 下午1:47:40 
	* @author 李斌
	* @return DatatablesViewPageBean<FeedOrderDetailBean> 
	* @throws
	 */
	public DatatablesViewPageBean<FeedOrderDetailBean> getFeedMaterialData(Map<String, String> map) {
		DatatablesViewPageBean<FeedOrderDetailBean> dtcpb = new DatatablesViewPageBean<FeedOrderDetailBean>();
		String loginDeptId = map.get("loginUserDeptId");
		if(!(loginDeptId!=null && !loginDeptId.trim().equals(""))) {
			throw new ServiceException("无部门人员不可领料");
		}
		map.put("isFeedOrderOut", "1");
		List<FeedOrderDetailBean> feedOrderDetailBeans = issueNoteMapper.getFeedMaterialData(map);
		if(!(feedOrderDetailBeans!=null && feedOrderDetailBeans.size()>0)) {
			throw new ServiceException("该物料无库存或无符合物料");
		}
		int count = issueNoteMapper.getFeedMaterialDataCount(map);
		dtcpb.setReturnData(feedOrderDetailBeans);
		dtcpb.setiTotalRecords(count);
		dtcpb.setiTotalDisplayRecords(count);
		dtcpb.setCode(200);
		return dtcpb;
	}
	
	/**
	 * 判断某投料单的料是否从车间退回到仓库中
	* @date 2018年9月29日 上午9:41:50 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public Double returnToMaterialByFeed(Map<String,Object> paramMap) {
		//原订单投料数
		BigDecimal oldFeedTotal = (BigDecimal) paramMap.get("oldFeedTotal");
		//申请修改的订单投料数
		BigDecimal newFeedTotal = (BigDecimal) paramMap.get("newFeedTotal");
		//投料单id
		String feedDetailId = (String) paramMap.get("feedDetailId");
		//订单编号
		String orderId = (String) paramMap.get("orderId");
		//行号
		String lineNo = (String) paramMap.get("lineNo");
		//物料代码
		String materialCode = (String) paramMap.get("materialCode");
		Assert.notNull(oldFeedTotal, "原订单投料数为空");
		Assert.notNull(newFeedTotal, "申请修改的订单投料数为空");
		Assert.notNull(feedDetailId, "投料单id为空");
		Assert.notNull(orderId, "订单编号为空");
		Assert.notNull(lineNo, "行号为空");
		Assert.notNull(materialCode, "物料代码为空");
		//投料单
		FeedOrderDetailBean feedOrderDetailBean = orderService.getFeedOrderDetailOneById(feedDetailId);
		Assert.notNull(feedOrderDetailBean, "投料单为空");
		//投料单物料单位投料数
		BigDecimal feedCount = new BigDecimal(feedOrderDetailBean.getFeedCount().toString());
		//投料单生产单位投料数
		BigDecimal productionFeedCount = new BigDecimal(feedOrderDetailBean.getProductionUnitFeedCount().toString());
		//从车间退回到仓库的物料(付/物料单位)
		List<WarehouseInOutDetailBean> returnToWarehouseMaterial = getReturnToMaterialByFeed(paramMap);
		if(returnToWarehouseMaterial ==null || returnToWarehouseMaterial.size()<1) {
			return 0.0;
		}
		//退回到仓库的物料(付)
		BigDecimal returnMaterialCountFu = new BigDecimal("0.0");
		//退回到仓库的物料单位数(物料单位)
		BigDecimal retrunMaterialCountMaterialUnit = new BigDecimal("0.0");
		for(WarehouseInOutDetailBean warehouseInOutDetailBean:returnToWarehouseMaterial) {
			//生产单位
			if("付".equals(warehouseInOutDetailBean.getInOutUnit())) {
				returnMaterialCountFu = returnMaterialCountFu.add(new BigDecimal(warehouseInOutDetailBean.getCount().toString()));
			}else {//物料单位
				retrunMaterialCountMaterialUnit = retrunMaterialCountMaterialUnit.add(new BigDecimal(warehouseInOutDetailBean.getCount().toString()));
			}
		}
		//将物料单位转换为付
		if(retrunMaterialCountMaterialUnit.doubleValue()>0) {
			Double returnMaterialToFuCoun = (feedCount.doubleValue()/retrunMaterialCountMaterialUnit.doubleValue())*(oldFeedTotal.subtract(productionFeedCount).doubleValue());
			returnMaterialCountFu = returnMaterialCountFu.add(new BigDecimal(returnMaterialToFuCoun.toString()));
		}
		return returnMaterialCountFu.doubleValue();
	}
	
	/**
	 * 通过投料单id获取退回到仓库的数据
	* @date 2018年9月29日 上午10:00:58 
	* @author 李斌
	* @return List<WarehouseInOutDetailBean> 
	* @throws
	 */
	public List<WarehouseInOutDetailBean> getReturnToMaterialByFeed(Map<String,Object> map){
		return warehouseMapper.getReturnToMaterialByFeed(map);
	}
	
	/**
	 * 发料到外协
	 * @param wiodb
	 * @param map
	 */
	public void addPutOutSourceByIssueNote(WarehouseInOutDetailBean wiodb,Map<String,Object> map) {
		if(wiodb.getSource() !=null && wiodb.getSource().intValue()==2) {
			Assert.notNull(wiodb, "出入库记录为空");
			Assert.notNull(map.get("loginCompany"), "登录公司名为空");
			Assert.notNull(map.get("feedDetailId"),"投料单id为空");
			Assert.notNull(map.get("cmtb"),"物料信息为空");
			//物料信息
			CompanyMaterialTableBean companyMaterialTableBean = (CompanyMaterialTableBean) map.get("cmtb");
			//投料单
			FeedOrderDetailBean feedOrderDetailBean = orderMapper.getFeedOrderDetailOneById(map.get("feedDetailId").toString());
			if(feedOrderDetailBean.getType()==2) {
				Map<String,String> feedMap = new HashMap<String,String>();
				feedMap.put("materialType", feedOrderDetailBean.getMaterialType());
				feedMap.put("materialFactory", feedOrderDetailBean.getMaterialFactory());
				feedMap.put("loginCompany", map.get("loginCompany").toString()); 
				feedMap.put("lineNo", feedOrderDetailBean.getLineNo());
				feedMap.put("feedOrderId", feedOrderDetailBean.getFeedOrderId());
				feedMap.put("materialCode", feedOrderDetailBean.getMaterialCode());
				feedMap.put("type", "1");
				feedMap.put("status", "1");
				List<FeedOrderDetailBean> feedOrderDetailBeans = orderMapper.getFeedOrderDetailByDetail(feedMap);
				if(feedOrderDetailBeans==null|| feedOrderDetailBeans.size()<1) {
					throw new ServiceException("未查询到生产订单投料单");
				} 
				feedOrderDetailBean = feedOrderDetailBeans.get(0);
			}
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			map.put("materialType", feedOrderDetailBean.getMaterialType());
			map.put("materialFactory", feedOrderDetailBean.getMaterialFactory()); 
			map.put("lineNo", feedOrderDetailBean.getLineNo());
			map.put("feedOrderDetailId", feedOrderDetailBean.getFeedOrderId());
			//获取订单明细
			OrderInfoDetailBean orderInfoDetailBean = orderMapper.getOrderInfoDetailByDetailMap(map); 
			if(orderInfoDetailBean==null||orderInfoDetailBean.getFeedTotal().equals("")) {
				throw new ServiceException("订单信息异常");
			}
			PutOutWarehouseBean putOutWarehouseBean = new PutOutWarehouseBean();
			putOutWarehouseBean.setId(wiodb.getId());
			putOutWarehouseBean.setOtherId(wiodb.getId());
			putOutWarehouseBean.setCompany(map.get("loginCompany").toString());
			putOutWarehouseBean.setOrderId(orderInfoDetailBean.getOrderNo());
			putOutWarehouseBean.setRowIndex(feedOrderDetailBean.getLineNo());
			putOutWarehouseBean.setMaterialType(feedOrderDetailBean.getMaterialType());
			putOutWarehouseBean.setApprovalTime(simpleDateFormat.format(new Date()));
			putOutWarehouseBean.setApprovalUser(map.get("loginUserId").toString());
			putOutWarehouseBean.setCreateUser(wiodb.getCreateUser());
			putOutWarehouseBean.setCreateTime(wiodb.getCreateTime());
			putOutWarehouseBean.setType(0);
			putOutWarehouseBean.setTypeId(putOutWarehouseBean.getId());
			//订单投料数 
			BigDecimal feedTotal = new BigDecimal(orderInfoDetailBean.getFeedTotal());
			//投料单投料数
			BigDecimal feedCount = new BigDecimal(feedOrderDetailBean.getFeedCount().toString());
			BigDecimal productionFeedCount = new BigDecimal("0.0");
			if(feedOrderDetailBean.getProductionUnitFeedCount().doubleValue()>0) {
				productionFeedCount = new BigDecimal(feedOrderDetailBean.getProductionUnitFeedCount());
			}
			//订单数与投料数不同,进行数量换算
			BigDecimal warehouseCount =new BigDecimal("0.0");
			//出库数
			BigDecimal outCount = new BigDecimal(wiodb.getCount().toString());
			//如果单位一致,那么就是物料单位出库
			int count = 0;
		
			if(wiodb.getSelfOutFuCount()==0){//不是自己填的
				//物料单位出库，目前模式下自己挑填的一定是付
				if(companyMaterialTableBean.getUnit().equals(wiodb.getInOutUnit())) {
					if(feedTotal.subtract(productionFeedCount).doubleValue()==0) {
						warehouseCount = outCount;
					}else if(feedTotal.subtract(productionFeedCount).doubleValue()<0) {//有物料单位投料数  
						warehouseCount =new BigDecimal(outCount.doubleValue()*((productionFeedCount.doubleValue()-feedTotal.doubleValue())/feedCount.doubleValue())+"");
					}else {
						warehouseCount =new BigDecimal(outCount.doubleValue()*((feedTotal.doubleValue()-productionFeedCount.doubleValue())/feedCount.doubleValue())+"");
					} 
				}else {  
					warehouseCount = outCount;
				} 
				count = (int)Math.floor(warehouseCount.doubleValue());
			}else {
				count = wiodb.getSelfOutFuCount();
			}
			Assert.isTrue(count>0, "发料到外协时,物料单位转换计算后,发料到外协数量不足一付,不可发料");
			putOutWarehouseBean.setCount(count);
			putOutWarehouseBean.setNoCount(0);
			//出入库出库数量
			putOutWarehouseBean.setMaterialCount(wiodb.getCount());
			//出入库单位
			putOutWarehouseBean.setMaterialUnit(wiodb.getInOutUnit());
			putOutWarehouseBean.setMaterialCode(wiodb.getMaterialCode());
			putOutWarehouseBean.setInOutType(1);
			putOutWarehouseBean.setSource(2);
			putOutWarehouseBean.setStatus(1);
			putOutWarehouseBean.setSourceName("原材料仓");
			putOutServiceNew.insertOnePutOutWarehouse(putOutWarehouseBean);
		}
	}
	
	/**
	 * 校验出库
	* @date 2018年10月15日 上午8:50:54 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public void checkOutMaterial(CompanyMaterialTableBean companyMaterialTableBean,WarehouseInOutDetailBean wiodb) {
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("materialCode", companyMaterialTableBean.getMaterialCode());
		paramMap.put("loginCompany", companyMaterialTableBean.getCompany());
		paramMap.put("warehouseType", wiodb.getWarehouseType());
		//原料辅料合计库存
		CompanyMaterialCountBean companyMaterialCountBean = companyMaterialCountService.getCompanyMaterialCountByMaterial(paramMap);
		//物料单位合格数
		Double materialCount = 0.0;
		//生产单位合格数
		Double productionCount = 0.0;
		if(companyMaterialCountBean.getCount()!=null) {
			materialCount = companyMaterialCountBean.getCount();
		}
		if(companyMaterialCountBean.getProductionUnitCount()!=null) {
			productionCount = companyMaterialCountBean.getProductionUnitCount();
		}
		//当前要出库数
		Double warehouseCount = wiodb.getCount();
		BigDecimal bigWarehouseCount = new BigDecimal(warehouseCount.toString());
		BigDecimal bigMaterialCount = new BigDecimal(materialCount.toString());
		BigDecimal bigProductionCount = new BigDecimal(productionCount.toString());
		//单位相同(物料单位)
		if(companyMaterialTableBean.getUnit().equals(wiodb.getInOutUnit())) {
			Assert.isTrue(bigMaterialCount.subtract(bigWarehouseCount).doubleValue()>=0, "物料单位库存不足");
		}else {//生产单位
			Assert.isTrue(bigProductionCount.subtract(bigWarehouseCount).doubleValue()>=0, "生产单位库存不足");
		}
	}
	
	/**
	 * 校验库存
	* @date 2018年10月13日 下午3:13:28 
	* @author 李斌
	* @return void 
	* @throws
	 */
	public void checkMaterialCount(CompanyMaterialCountBean companyMaterialCountBean,CompanyMaterialTableBean companyMaterialTableBean,WarehouseInOutDetailBean wiodb) {
		CompanyMaterialCountBean mapCount  = warehouseMapper.getWarehouseOutByNotStatus(companyMaterialCountBean);
		BigDecimal bigMaterialCount = new BigDecimal("0.0");
		BigDecimal bigProductionCount = new BigDecimal("0.0");
		BigDecimal bigMaterialNoStatusCount = new BigDecimal("0.0");
		BigDecimal bigProductionNoStatusCount = new BigDecimal("0.0");
		if(companyMaterialCountBean.getCount()!=null) {
			bigMaterialCount = new BigDecimal(companyMaterialCountBean.getCount().toString());
		}
		if(companyMaterialCountBean.getProductionUnitCount()!=null) {
			bigProductionCount = new BigDecimal(companyMaterialCountBean.getProductionUnitCount().toString());
		}
		if(mapCount.getCount() !=null) {
			bigMaterialNoStatusCount = new BigDecimal(mapCount.getCount().toString());
		}
		if(mapCount.getProductionUnitCount() !=null) {
			bigProductionNoStatusCount = new BigDecimal(mapCount.getProductionUnitCount().toString());
		}
		//当前要出库数
		BigDecimal bigWarehouseCount = new BigDecimal(wiodb.getCount().toString());
		//单位相同(物料单位)
		if(companyMaterialTableBean.getUnit().equals(wiodb.getInOutUnit())) {
			Assert.isTrue(bigMaterialCount.subtract(bigMaterialNoStatusCount).subtract(bigWarehouseCount).doubleValue()>=0, "物料单位库存不足");
		}else {//生产单位
			Assert.isTrue(bigProductionCount.subtract(bigProductionNoStatusCount).subtract(bigWarehouseCount).doubleValue()>=0, "生产单位库存不足");
		}
	}
	
	/**
	 * 校验用户写的交接入库付数
	* @date 2018年10月29日 下午1:34:29 
	* @author 李斌
	* @return void 
	* @throws
	 */
//	public void checkSelfOutFuCount(FeedOrderDetailBean feedOrderDetailBean,WarehouseInOutDetailBean wiodb) {
//		Assert.notNull(feedOrderDetailBean, "投料单明细为空");
//		Assert.notNull(wiodb, "出入库记录为空");
//		if(wiodb.getSelfOutFuCount()>0) {
//			Map<String,Object> orderMap = new HashMap<String,Object>();
//			orderMap.put("feedOrderDetailId", feedOrderDetailBean.getFeedOrderId());
//			orderMap.put("materialType", feedOrderDetailBean.getMaterialType());
//			orderMap.put("lineNo", feedOrderDetailBean.getLineNo());
//			orderMap.put("materialFactory", feedOrderDetailBean.getMaterialFactory());
//			orderMap.put("loginCompany", wiodb.getCompany());
//			//查询订单明细
//			OrderInfoDetailBean orderInfoDetailBean = orderMapper.getOrderInfoDetailByDetailMap(orderMap); 
//			//查询报工交接数
//			FeedingAndReportBean feedingAndReportBean=workshopService.GetOrderSystemCount(feedOrderDetailBean.getOrderId(), feedOrderDetailBean.getMaterialType(), feedOrderDetailBean.getLineNo());
//			feedingAndReportBean.setFeddingCount(Long.parseLong(orderInfoDetailBean.getFeedTotal()));
//			//校验数量
//			Assert.isTrue(wiodb.getSelfOutFuCount()<=(feedingAndReportBean.getFeddingCount()-feedingAndReportBean.getWorkShopCount()-feedingAndReportBean.getFinishCount()-feedingAndReportBean.getPutOutCount()),
//					feedOrderDetailBean.getMaterialType()+"已有:车间:"+feedingAndReportBean.getWorkShopCount()+"、外协:"+feedingAndReportBean.getPutOutCount()+"、成品:"+feedingAndReportBean.getFinishCount()+",最多还可交接入库"+(feedingAndReportBean.getFeddingCount()-feedingAndReportBean.getWorkShopCount()-feedingAndReportBean.getFinishCount()-feedingAndReportBean.getPutOutCount())+"付");
//		}
//	}
	
	//校验投料单是否完成领料
	private boolean checkFeedOrderIsFinish(FeedOrderDetailBean feedDeatil, WarehouseInOutDetailBean inOut,boolean isUpdate,int oldSelfOutFuCount) {
		int nowSelfOutFuCount = 0;
		if(inOut.getSelfOutFuCount()>0) {
			nowSelfOutFuCount = inOut.getSelfOutFuCount();
		}else {
			if("付".equals(inOut.getInOutUnit())) {
				nowSelfOutFuCount = inOut.getCount().intValue();
			}
		}
		//之前投料单发料领料记录
		List<WarehouseInOutDetailBean> warehouseInOutDetailList = warehouseMapper.getWarehouseOutDetailByFeedOrNotApproval(feedDeatil);
		//订单投料数
		int feedAllTotal = 0;
		if(feedDeatil.getType().equals(2)) {//申补   获取正常投料的数量
			Map<String,String> feedMap = new HashMap<String,String>();
			feedMap.put("materialType", feedDeatil.getMaterialType());
			feedMap.put("materialFactory", feedDeatil.getMaterialFactory());
			feedMap.put("loginCompany", inOut.getCompany()); 
			feedMap.put("lineNo", feedDeatil.getLineNo());
			feedMap.put("feedOrderId", feedDeatil.getFeedOrderId());
			feedMap.put("materialCode", feedDeatil.getMaterialCode());
			feedMap.put("type", "1");
			feedMap.put("status", "1");
			List<FeedOrderDetailBean> feedOrderDetailBeans = orderMapper.getFeedOrderDetailByDetail(feedMap);
			Assert.isTrue(feedOrderDetailBeans !=null && feedOrderDetailBeans.size()>0, "未查询到生产订单投料单");
			feedDeatil = feedOrderDetailBeans.get(0);
		}
		//查询订单明细
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("materialType", feedDeatil.getMaterialType());
		paramMap.put("materialFactory", feedDeatil.getMaterialFactory()); 
		paramMap.put("lineNo", feedDeatil.getLineNo());
		paramMap.put("feedOrderDetailId", feedDeatil.getFeedOrderId());
		paramMap.put("loginCompany", inOut.getCompany());
		//获取订单明细
		OrderInfoDetailBean orderInfoDetailBean = orderMapper.getOrderInfoDetailByDetailMap(paramMap); 
		//订单投料数 
		BigDecimal feedTotal = new BigDecimal(orderInfoDetailBean.getFeedTotal());
		for(WarehouseInOutDetailBean wiodb:warehouseInOutDetailList) {
			//代表单位相同,物料单位
			if(wiodb.getIsEquals()==1) {
				if(wiodb.getSelfOutFuCount()==0) {
					//投料单投料数
					BigDecimal feedCount = new BigDecimal(feedDeatil.getActualFeedCount().toString());
					BigDecimal productionFeedCount = new BigDecimal("0.0");
					//有物料单位投料数
					if(feedDeatil.getProductionUnitFeedCount().doubleValue()>0) {
						productionFeedCount = new BigDecimal(feedDeatil.getProductionUnitFeedCount());
					}
					if(feedTotal.subtract(productionFeedCount).doubleValue()==0) {
						feedAllTotal += wiodb.getCount();
					}else if(feedTotal.subtract(productionFeedCount).doubleValue()<0) {
						feedAllTotal += wiodb.getCount().doubleValue()*((productionFeedCount.doubleValue()-feedTotal.doubleValue())/feedCount.doubleValue());
					}else {
						feedAllTotal += wiodb.getCount().doubleValue()*((feedTotal.doubleValue()-productionFeedCount.doubleValue())/feedCount.doubleValue());
					} 
				}else {
					feedAllTotal += wiodb.getSelfOutFuCount();
				}
			}else {//生产单位
				feedAllTotal += wiodb.getCount();
			}
		}
		//加上这次用户手填的出库付数
		if(!isUpdate) {
			feedAllTotal+= nowSelfOutFuCount;
		}else {
			feedAllTotal= feedAllTotal - nowSelfOutFuCount+oldSelfOutFuCount;
		}
		if(feedAllTotal>=feedTotal.intValue()) {
			return true;
		}
		return false;
	}
	
	/**
	 * 获取成品出库数量
	 * @param map
	 * @return
	 */
	public List<FinishStockBean> getFinishOutOrder(Map<String, Object> map) {
		List<FinishStockBean> finishList = warehouseMapper.getFinishOutOrder(map);
		return finishList;
	}



	/**
	 * 无采购单入库的物料出库给订单
	 * 首先 补全物料保存为投料单采购单,
	 * 随后 投料单领料
	 * @param map
	 * @throws CloneNotSupportedException 
	 */
	public void saveOutToOrder(Map<String, Object> map,HttpServletRequest request) throws CloneNotSupportedException {
		Assert.notNull(map.get("materialData"), "物料信息为空");
		Assert.notNull(map.get("orderData"), "订单信息为空");
		Assert.notNull(map.get("type"), "类型为空");
		CompanyMaterialTableBean companyMaterialTable = JSONObject.parseObject(map.get("materialData").toString(),CompanyMaterialTableBean.class);
		OrderInfoDetailBean orderInfoDetail = JSONObject.parseObject(map.get("orderData").toString(),OrderInfoDetailBean.class);
		List<FeedOrderDetailBean> feedOrderDetailList = warehouseMapper.getFeedOrderDetailByOrderDetail(orderInfoDetail);
		Assert.isTrue(feedOrderDetailList==null || feedOrderDetailList.size()==0, "该订单已经生成过投料单了,不能用于出库");
		CompanyBean companyBean = compangMapper.getCompany(map);
		Map<String,Object> materialMap = new HashMap<String,Object>();
		materialMap.put("company", map.get("loginCompany"));
		materialMap.put("materialCode", companyMaterialTable.getMaterialCode());
		List<CompanyMaterialTableBean> companyMaterialTableBean = companyMaterialMapper
				.getCompanyMaterialByMap(materialMap);
		Assert.isTrue(companyMaterialTableBean.size()==1, "该物料被禁用,请到物料表查询");
		if(companyBean.getIsNeedApprovalByMaterial()==1) {
			Assert.isTrue(companyMaterialTableBean.get(0).getPurchaseApproval().equals(1), "物料名称:"+companyMaterialTableBean.get(0).getMaterialName()+" 色号:"+companyMaterialTableBean.get(0).getColor()+"还未审核,请先审核物料");
		}
		//调用补全订单service
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("id", orderInfoDetail.getId());
		paramMap.put("materialCode", companyMaterialTable.getMaterialCode());
		paramMap.put("loginCompany", map.get("loginCompany"));
		paramMap.put("outCount",map.get("outCount"));
		paramMap.put("selfOutFuCount",map.get("selfOutFuCount"));
		paramMap.put("loginUserId", map.get("loginUserId"));
		paramMap.put("loginUserName", map.get("loginUserName"));
		//校验各种数量
		this.checkDetailCount(companyMaterialTable, orderInfoDetail, paramMap);
		//补全订单
		int updateOrderRow =  basicDataService.updateOrderInfoDetailByCompanyMaterialCode(paramMap);
		Assert.isTrue(updateOrderRow==1, "操作失败,补全订单信息失败");
		//保存投料单与采购单
		Map<String,Object> feedOrderDetailMap =  this.selfSaveFeedAndPurchase(companyMaterialTable, orderInfoDetail,map);
		//出库
		this.selfSaveOutToOrder(feedOrderDetailMap,companyMaterialTable,map,request);
	}
	
	//无订单物料出库给订单,后台自主保存为投料单和采购单并且默认审核
	private Map<String,Object> selfSaveFeedAndPurchase(CompanyMaterialTableBean companyMaterialTable, OrderInfoDetailBean orderInfoDetail,Map<String,Object> map) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		map.put("orderId", orderInfoDetail.getOrderNo());
		String feedOrderId = null;
		FeedOrderMainBean oldFeedOrderMain = orderMapper.getFeedOrderMainByOrderId(map);
		//如果没有该订单的投料单主表,就插入一条
		if(oldFeedOrderMain==null) {
			feedOrderId = StringUtil.getUUID();
			Map<String, Object> hashMap = new HashMap<String, Object>();
			hashMap.put("id", feedOrderId);
			hashMap.put("status", 1);
			hashMap.put("loginUserId", map.get("loginUserId").toString());
			hashMap.put("createTime", sdf.format(new Date()));
			hashMap.put("orderId", orderInfoDetail.getOrderNo());
			hashMap.put("loginCompany", map.get("loginCompany").toString());
			int row = orderMapper.insertFeedMian(hashMap);
			Assert.isTrue(row>0, "操作失败,投料单主表保存失败");
		}else {
			feedOrderId = oldFeedOrderMain.getId();
		}
		Map<String,Object> feedOrderDetailMap = new HashMap<String,Object>();
		//设置id
		feedOrderDetailMap.put("id",StringUtil.getUUID());
		feedOrderDetailMap.put("feedOrderId", feedOrderId);
		feedOrderDetailMap.put("materialCode", companyMaterialTable.getMaterialCode());
		feedOrderDetailMap.put("feedCount", orderInfoDetail.getFeedCount());
		feedOrderDetailMap.put("isBuild", 1);
		feedOrderDetailMap.put("isReceiveFinish", 0);
		feedOrderDetailMap.put("receiveCount", 0);
		feedOrderDetailMap.put("productionUnitReceiveCount", 0);
		feedOrderDetailMap.put("status", 1);
		feedOrderDetailMap.put("type", 1);// 为1是生产订单投料单
		feedOrderDetailMap.put("materialName", companyMaterialTable.getMaterialName());
		feedOrderDetailMap.put("color", companyMaterialTable.getColor());
		feedOrderDetailMap.put("model", companyMaterialTable.getModel());
		feedOrderDetailMap.put("providerName", companyMaterialTable.getProviderName());
		feedOrderDetailMap.put("approvalUser", map.get("loginUserId"));
		feedOrderDetailMap.put("approvalTime", sdf.format(new Date()));
		feedOrderDetailMap.put("approvalReason", "物料出库给订单,后台自动生成审核");
		feedOrderDetailMap.put("tax", 0);
		feedOrderDetailMap.put("purchasePrice",0);
		feedOrderDetailMap.put("createTime", sdf.format(new Date()));
		feedOrderDetailMap.put("createUser", map.get("loginUserId"));
		feedOrderDetailMap.put("lineNo", orderInfoDetail.getLineNo());
		feedOrderDetailMap.put("materialType", orderInfoDetail.getMaterialType());
		feedOrderDetailMap.put("materialFactory", orderInfoDetail.getMaterialFactory());
		int row = orderMapper.insertFeedOrderDetailOne(feedOrderDetailMap);
		Assert.isTrue(row>0, "操作失败,保持投料单失败");
		
		//保存采购单
		Map<String,Object> purchaseMap = new HashMap<String,Object>();
		PurchaseOrderBean purchaseOrder = new PurchaseOrderBean();
		String cgId = dingTalkMapper.getApprovalNo("CG");
		purchaseOrder.setFeedDetailId(feedOrderDetailMap.get("id").toString());
		purchaseOrder.setId(cgId);
		purchaseOrder.setPurchaseDetailId(StringUtil.getUUID());
		purchaseOrder.setType(1);
		purchaseOrder.setStatus(1);
		purchaseOrder.setInCount(0.0);
		purchaseOrder.setIsFinish(0);
		purchaseOrder.setPurchasePeople(map.get("loginUserId").toString());
		purchaseOrder.setMaterialCode(companyMaterialTable.getMaterialCode());
		purchaseOrder.setMaterialName(companyMaterialTable.getMaterialName());
		purchaseOrder.setModel(companyMaterialTable.getModel());
		purchaseOrder.setColor(companyMaterialTable.getColor());
		purchaseOrder.setProviderName(companyMaterialTable.getProviderName());
		purchaseOrder.setCurrency("人民币");
		purchaseOrder.setIsPrint(0);
		purchaseOrder.setLineNo(orderInfoDetail.getLineNo());
		purchaseOrder.setMaterialType(orderInfoDetail.getMaterialType());
		purchaseOrder.setMaterialFactory(orderInfoDetail.getMaterialFactory());
		purchaseOrder.setPurchaseCount(0.0);
		purchaseOrder.setOrderId(orderInfoDetail.getOrderNo());
		purchaseOrder.setPrice(0.0);
		purchaseOrder.setTax(0.0);
		purchaseOrder.setCreateTime(sdf.format(new Date()));
		purchaseOrder.setCreateUser(map.get("loginUserId").toString());
		purchaseOrder.setApprovalUser(map.get("loginUserId").toString());
		purchaseOrder.setApprovalTime(purchaseOrder.getCreateTime());
		purchaseOrder.setApprovalReason("物料出库给订单,后台自动生成审核");
		purchaseOrder.setCompany(map.get("loginCompany").toString());
		List<PurchaseOrderBean> purchaseOrderBeanList = new ArrayList<PurchaseOrderBean>();
		purchaseOrderBeanList.add(purchaseOrder);
		purchaseMap.put("purchaseOrderBeanList", purchaseOrderBeanList);
		int purchaseRow = purchaseOrderMapper.savePurchaseOrder(purchaseMap);
		Assert.isTrue(purchaseRow>0, "操作失败,采购单保存失败");
		purchaseOrderBeanList.clear();
		purchaseMap.clear();
		return feedOrderDetailMap;
	}
	
	/**
	 * 物料自主出库给订单
	 * @param feedOrderDetailMap
	 * @throws CloneNotSupportedException 
	 */
	private void selfSaveOutToOrder(Map<String,Object> feedOrderDetailMap,CompanyMaterialTableBean companyMaterialTable,Map<String,Object> map,HttpServletRequest request) throws CloneNotSupportedException {
		Map<String,String> saveOutOrderMap = new HashMap<String,String>();
		saveOutOrderMap.put("loginCompany", map.get("loginCompany").toString());
		saveOutOrderMap.put("loginUserId", map.get("loginUserId").toString());
		saveOutOrderMap.put("loginUserName", map.get("loginUserName").toString());
		saveOutOrderMap.put("loginUserDeptId", map.get("loginUserDeptId").toString());
		List<WarehouseInOutDetailBean> inOutList = new ArrayList<WarehouseInOutDetailBean>();
		WarehouseInOutDetailBean inOutBean = new WarehouseInOutDetailBean();
		inOutBean.setMaterialCode(feedOrderDetailMap.get("materialCode").toString());
		inOutBean.setMaterialName(feedOrderDetailMap.get("materialName").toString());
		inOutBean.setColor(feedOrderDetailMap.get("color").toString());
		inOutBean.setProviderName(feedOrderDetailMap.get("providerName").toString());
		inOutBean.setModel(feedOrderDetailMap.get("model").toString());
		inOutBean.setType(2);
		inOutBean.setWarehouseType(4);
		inOutBean.setIsProductionUnit(0);
		int sourceType = Integer.parseInt(map.get("type").toString());
		inOutBean.setSourceType(sourceType);
		if(sourceType==1) {
			inOutBean.setPickingPeople(map.get("pickingPeople").toString());
			inOutBean.setWorkShopId(map.get("workShopId").toString());
			inOutBean.setDeptId(map.get("deptId").toString());
		}
		inOutBean.setCount(Double.valueOf(map.get("outCount").toString()));
		inOutBean.setFeedOrder(feedOrderDetailMap.get("id").toString());
		if(!"付".equals(companyMaterialTable.getUnit())) {
			inOutBean.setSelfOutFuCount(Integer.parseInt(map.get("selfOutFuCount").toString()));
		}
		inOutList.add(inOutBean);
		JSONArray jsonArray = JSONArray.fromObject(inOutList);
		saveOutOrderMap.put("metailArray", jsonArray.toString());
		this.saveWarehouseOut(saveOutOrderMap,request);
	}
	
	/**
	 * 校验数量
	 * @param companyMaterialTable
	 * @param orderInfoDetail
	 * @param map
	 */
	private void checkDetailCount(CompanyMaterialTableBean companyMaterialTable,OrderInfoDetailBean orderInfoDetail,Map<String,Object> map) {
		//出库数量
		Assert.notNull(map.get("outCount"), "出库数量为空");
		double outCount = Double.parseDouble(map.get("outCount").toString());
		Assert.notNull(orderInfoDetail.getFeedCount(), "物料投料数为空");
		double feedCount = orderInfoDetail.getFeedCount();
		Assert.isTrue(feedCount>=outCount, "出库数不能大于投料数");
		int selfOutFuCount = 0; 
		if(!"付".equals(companyMaterialTable.getUnit())) {
			Assert.notNull(map.get("selfOutFuCount"),"交接数为空");
			selfOutFuCount = Integer.parseInt(map.get("selfOutFuCount").toString());
		}
		int feedTotal = Integer.parseInt(orderInfoDetail.getFeedTotal());
		Assert.isTrue(feedTotal>=selfOutFuCount, "交接数不能大于订单投料数");
		double receiveCount = purchaseOrderService.getReceiveCountByFeedCount(map.get("loginCompany").toString(), companyMaterialTable.getMaterialCode());
		Assert.isTrue(receiveCount>=feedCount, "库存数不足投料数");
	}

	/**
	 * 半成品出库
	 * @param map
	 * @return
	 */
	public DatatablesViewPageBean<WarehouseInOutDetailBean> getBlankMaterialData(Map<String, String> map) {
		DatatablesViewPageBean<WarehouseInOutDetailBean> dtvpb = new DatatablesViewPageBean<WarehouseInOutDetailBean>();
		List<WarehouseInOutDetailBean> dataList = warehouseMapper.getBlankMaterialData(map);
		int count = warehouseMapper.getBlankMaterialCount(map);
		dtvpb.setiTotalDisplayRecords(count);
		dtvpb.setiTotalRecords(count);
		dtvpb.setReturnData(dataList);
		return dtvpb;
	}


    /**
     * 半成品出库
     * @param wiodb
     * @param map
     * @param request 
     * @return
     * @throws CloneNotSupportedException 
     */
	public String saveBlankMaterialToCustomer(WarehouseInOutDetailBean wiodb,Map<String, String> map, HttpServletRequest request) throws CloneNotSupportedException {
		List<WarehouseInOutDetailBean> saveList = new ArrayList<WarehouseInOutDetailBean>();
		//出库Id
		String ckId = dingTalkMapper.getApprovalNo("CK");
		wiodb.setId(ckId);
		wiodb.setStatus(0);
		wiodb.setCreateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
		wiodb.setCreateUser(map.get("loginUserId"));
		wiodb.setCompany(map.get("loginCompany"));
		checkBlankMaterialToCustomerCount(wiodb);
		saveList.add(wiodb);
		this.checkTakingIsNotApproval(saveList, map.get("loginCompany"));
		companyMaterialMapper.insertInOutRecode(saveList);
		//是否是过账审核
		boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		String mString="";
		if(isAduit) {
			Map<String,String> aduitMap=this.setAduitMap(map);
			aduitMap.put("id", wiodb.getId());
			this.approvalWarehouse(aduitMap,1,request);
		}else {
			String queryCondition = "?ids="+ckId;
			mString=companyMaterialService.sendWechatMessage("半成品出库给客户", 2, "半成品出库给客户", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 2);
		}
		return mString;
	}
	
	//校验半成品出库数量
	private void checkBlankMaterialToCustomerCount(WarehouseInOutDetailBean wiodb) {
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("loginCompany", wiodb.getCompany());
		map.put("materialCode", wiodb.getMaterialCode());
		map.put("warehouseType", wiodb.getWarehouseType());
		List<CompanyMaterialCountBean> companyMaterialList = companyMaterialCountService.getCompanyMaterialCountListByDetail(map);
		Assert.isTrue(!companyMaterialList.isEmpty(), "库存信息为空");
		CompanyMaterialCountBean cmcb = companyMaterialList.get(0);
		//半成品库存数
		BigDecimal blankMaterialCount = new BigDecimal(cmcb.getCount().toString());
		//未审核的半成品出库数
		BigDecimal notApprovalBlankMaterialCount = warehouseMapper.getNotApprovalBlankMaterialCount(wiodb.getMaterialCode(),wiodb.getCompany());
		//本次要出库的数据
		BigDecimal outCount = new BigDecimal(wiodb.getCount().toString());
		Assert.isTrue(blankMaterialCount.subtract(notApprovalBlankMaterialCount).subtract(outCount).doubleValue()>=0, "库存不足 最多还可出库"+blankMaterialCount.subtract(notApprovalBlankMaterialCount).doubleValue()+"付");
	}
	
	
	/**
	 * 库存盘点
	 * type 类型  11盘点入库   12 盘点出库
	 * orderId (订单编号)
	 * rowIndex 行号
	 * materialCode (原料盘点时用 物料代码)
	 * count 数量
	 * warehouseType 仓库类型
	 * noCount 不合格数
	 * jsonArray (批量字符串)
	 * @param request 
	 * @param request
	 * @param sourceType 5库存盘点  6物料换仓
	 * @return
	 * @throws CloneNotSupportedException 
	 */
	public String materialStockTaking(Map map, HttpServletRequest request, int sourceType) throws CloneNotSupportedException  {
		StringUtil.checkIsTrue(map, "jsonArray", "未获取到参数");
		String jsonArray=map.get("jsonArray").toString();
		JSONArray json=JSONArray.fromObject(jsonArray);
		SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dateStr=simpleDateFormat.format(new Date());
		String loginUserId=map.get("loginUserId").toString();
		String loginCompany=map.get("loginCompany").toString();
		List<WarehouseInOutDetailBean> warehouseInOutDetailBeans=(List<WarehouseInOutDetailBean>) JSONArray.toCollection(json, WarehouseInOutDetailBean.class);
		Assert.isTrue(null!=warehouseInOutDetailBeans && warehouseInOutDetailBeans.size()>0,"参数不正确");
		this.checkMaterialIsHaveNotApproval(warehouseInOutDetailBeans,map.get("loginCompany").toString());
		for(WarehouseInOutDetailBean inOutDetailBean:warehouseInOutDetailBeans) {
			inOutDetailBean.setCreateUser(loginUserId);
			inOutDetailBean.setCreateTime(dateStr);
			inOutDetailBean.setCompany(loginCompany);
			inOutDetailBean.setStatus(0);
			inOutDetailBean.setSourceType(sourceType);//是库存盘点
			//入库出库设置id
			if(inOutDetailBean.getType()==11) {
				inOutDetailBean.setId(CreateIdUtil.getId(CreateIdUtil.WAREHOUSE_IN));
			}
			if(inOutDetailBean.getType()==12) {
				inOutDetailBean.setId(CreateIdUtil.getId(CreateIdUtil.WAREHOUSE_OUT));
			}
		}
		int row=companyMaterialMapper.insertInOutRecode(warehouseInOutDetailBeans);
		Assert.isTrue(row>0,ReturnStringUtil.OPERATION_ERROR);
		//是否是过账审核
		boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		String msg="";
		if(isAduit) {
			Map<String,String> aduitMap=this.setAduitMap(map);
		    for(WarehouseInOutDetailBean warehouseInOutDetailBean:warehouseInOutDetailBeans) {
		    	aduitMap.put("id", warehouseInOutDetailBean.getId());
		    	this.approvalWarehouse(aduitMap,1,request);
		    }
		}else {
			String bodyMessage =sourceType==5?"条库存盘点单需审核":"条库存转仓单需审核"; 
			List<String> message=warehouseInOutDetailBeans.stream().map(WarehouseInOutDetailBean::getId).collect(Collectors.toList());
			String queryCondition = "?ids="+message.toString().substring(1,message.toString().length()-1).replace(" ","");
			msg = companyMaterialService.sendWechatMessage("入库单待审核", 2, message.size()+bodyMessage, simpleDateFormat.format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 1);
		}
		return ReturnStringUtil.OPERATION_SUCCESS+msg;
	}


	/**
	 * 校验物料是否有未审核的出入库记录
	 * @param warehouseInOutDetailBeans
	 */
	private void checkMaterialIsHaveNotApproval(List<WarehouseInOutDetailBean> warehouseInOutDetailBeans,String company) {
		int warehouseType=warehouseInOutDetailBeans.get(0).getWarehouseType().intValue();
		List<WarehouseInOutDetailBean> notApprovalRecordList=warehouseMapper.getNotApprovalInOutRecord(company);
		if (null!=notApprovalRecordList && notApprovalRecordList.size()>0) {
			for(WarehouseInOutDetailBean widb:warehouseInOutDetailBeans) {
				//如果是成品仓
				if(1==widb.getWarehouseType()) {
					List<WarehouseInOutDetailBean> list=notApprovalRecordList.stream().filter(pp->pp.getOrderId().equals(widb.getOrderId()) && pp.getRowIndex().equals(widb.getRowIndex())).collect(Collectors.toList());
					if(list.size()>0) {
						Assert.isTrue(false,"订单编号"+list.get(0).getCompanyOrderId()+"有成品出入库记录未审核,不可盘点/转仓");
					}
				}else {
					List<WarehouseInOutDetailBean> list=notApprovalRecordList.stream().filter(pp->pp.getMaterialCode().equals(widb.getMaterialCode())).collect(Collectors.toList());
					if(list.size()>0) {
						Assert.isTrue(false,"物料"+list.get(0).getMaterialName()+"有物料出入库记录未审核,不可盘点/转仓");
					}
				}
			}
		}
	}
	/**
	 * 检验是否有盘点记录未审核
	 * @param warehouseInOutDetailBeans
	 */
	public void  checkTakingIsNotApproval(List<WarehouseInOutDetailBean> warehouseInOutDetailBeans,String company) {
		List<WarehouseInOutDetailBean> notApprovalRecordList=warehouseMapper.getNotApprovalInOutRecord(company);
		if (null!=notApprovalRecordList && notApprovalRecordList.size()>0) {
			notApprovalRecordList=notApprovalRecordList.stream().filter(pp->pp.getType()==11 || pp.getType()==12).collect(Collectors.toList());
			for(WarehouseInOutDetailBean widb:warehouseInOutDetailBeans) {
				//如果是成品仓
				if(1==widb.getWarehouseType()) {
					List<WarehouseInOutDetailBean> list=notApprovalRecordList.stream().filter(pp->pp.getOrderId().equals(widb.getOrderId()) && pp.getRowIndex().equals(widb.getRowIndex())).collect(Collectors.toList());
					if(list.size()>0) {
						Assert.isTrue(false,"订单编号"+list.get(0).getCompanyOrderId()+"成品盘点中,不可操作");
					}
				}else {
					List<WarehouseInOutDetailBean> list=notApprovalRecordList.stream().filter(pp->pp.getMaterialCode().equals(widb.getMaterialCode())).collect(Collectors.toList());
					if(list.size()>0) {
						Assert.isTrue(false,"物料"+list.get(0).getMaterialName()+"物料盘点中,不可操作");
					}
				}
			}
		}
	}


    /**
     * 车间需退回数量
     * @param map
     * @return
     */
	public DatatablesViewPageBean<FeedOrderDetailBean> workShopNeedReturnMaterial(Map<String, String> map) {
		List<FeedOrderDetailBean> list=warehouseMapper.workShopNeedReturnMaterial(map);
		int  count=warehouseMapper.workShopNeedReturnMaterialCount(map);
		//设置领料比例
		list=this.setReceiveBiLi(list);
		DatatablesViewPageBean<FeedOrderDetailBean> datatablesViewPageBean=new DatatablesViewPageBean<FeedOrderDetailBean>();
		datatablesViewPageBean.setReturnData(list);
		datatablesViewPageBean.setiTotalDisplayRecords(count);
		datatablesViewPageBean.setiTotalRecords(count);
		return datatablesViewPageBean;
	}




	/**
	 * 设置车间领料，物料单位和生产单位比例
	 * @param list
	 * @return
	 */
	private List<FeedOrderDetailBean> setReceiveBiLi(List<FeedOrderDetailBean> list) {
		Set<String> orderIdSet=list.stream().map(FeedOrderDetailBean::getOrderId).collect(Collectors.toSet());
		Map map=new HashMap();
		map.put("orderIdSet", orderIdSet);
		List<ReportBean> reportBeans=workshopService.getMaterialUnit(map);
		reportBeans = reportBeans == null ?new ArrayList<ReportBean>():reportBeans;
		for(FeedOrderDetailBean feed:list) {
			//设置同一个订单编号，行号，物料类型，物料代码的发料总数和交接付数
			List<ReportBean> filterList=reportBeans.stream().filter(pp->pp.getOrderId().equals(feed.getOrderId()) && pp.getRowIndex().equals(feed.getLineNo()) && pp.getMachining().equals(feed.getMaterialType()) && pp.getMaterialCode().equals(feed.getMaterialCode())).collect(Collectors.toList());
			if(filterList.size()<=0) {
				feed.setBiLi(1.0);
			}else {
				ReportBean rr=filterList.get(0);
				feed.setBiLi(rr.getQualified()/rr.getMaterialCount());
			}
		}
		return list;
	}




	/**
	 * 车间多余物料退回至仓库
	 * orderId 订单编号
	 * rowIndex 行号
	 * machining 物料类型
	 * materialCode 物料代码
	 * workShopName 车间id
	 * materialCount 物料单位退回数量
	 * @param request 
	 * @return
	 */
	public String workShopSurplusMaterialReturnToWarehouse(Map<String, String> map, HttpServletRequest request) {
		StringUtil.checkIsTrue(map, "orderId", "未获取到订单编号");
		StringUtil.checkIsTrue(map, "rowIndex", "未获取到行号");
		StringUtil.checkIsTrue(map, "machining", "未获取到物料类型");
		StringUtil.checkIsTrue(map, "materialCode", "未获取到物料代码");
		StringUtil.checkIsTrue(map, "workShopName", "未获取到车间id");
		ReportBean reportBean = null;
		try {
			reportBean=(ReportBean) shoppingMallService.mapToObject(map, ReportBean.class);
		} catch (Exception e) {
			Assert.notNull(null,"类型转换异常");
		}
		SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		String dateString=simpleDateFormat.format(new Date());
		simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
		String dayString=simpleDateFormat.format(new Date());
		Boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		String returnStr=this.workShopSurplusMaterialReturnToWarehouse(reportBean,map,dateString,dayString,isAduit,request);
		return ReturnStringUtil.SAVE_SUCCESS+returnStr;
	}

    /**
     * 单个生成车间退回多余物料到仓库
     * @param reportBean
     * @param map
     * @param dateString 
     * @param dayString 
     * @param request 
     */
	private String  workShopSurplusMaterialReturnToWarehouse(ReportBean reportBean, Map<String, String> map, String dateString, String dayString,boolean isAduit, HttpServletRequest request) {
		//一 先判断   车间是否有足够的物料多余
		map.put("orderId", reportBean.getOrderId());
		List<FeedOrderDetailBean> list=warehouseMapper.workShopNeedReturnMaterial(map);
		Assert.isTrue(null!=list && list.size()>0,"订单编号"+reportBean.getOrderId()+"没有可退回多余物料");
		List<FeedOrderDetailBean> filterAfterList=list.stream().filter(feed->feed.getOrderId().equals(reportBean.getOrderId()) && feed.getMaterialType().equals(reportBean.getMachining()) && feed.getLineNo().equals(reportBean.getRowIndex()) && feed.getMaterialCode().equals(reportBean.getMaterialCode())).collect(Collectors.toList());
		Assert.isTrue(filterAfterList.size() > 0 ,"订单编号："+reportBean.getOrderId()+",物料类型："+reportBean.getMachining()+",行号："+reportBean.getRowIndex()+"没有可退回多余物料");
		FeedOrderDetailBean feedOrderDetailBean = filterAfterList.get(0);
		Assert.isTrue(feedOrderDetailBean.getReceiveCount() - feedOrderDetailBean.getFeedCount() >= reportBean.getMaterialCount(),"订单编号："+reportBean.getOrderId()+",物料类型："+reportBean.getMachining()+",行号："+reportBean.getRowIndex()+"退回数不可超过多余数"+(feedOrderDetailBean.getReceiveCount() - feedOrderDetailBean.getFeedCount()));
		reportBean.setTouchPeople(map.get("loginUserId"));//报工人为登录人
		reportBean.setTime(dayString);
		reportBean.setCompany(map.get("loginCompany"));
		reportBean.setTouchTime(dateString);
		reportBean.setMachingType(0);
		reportBean.setTypeId(StringUtil.getUUID());
		reportBean.setOtherType(2);//退回至车间
		reportBean.setNoQualified(0);
		reportBean.setStatus(0);
		reportBean.setUnit(feedOrderDetailBean.getUnit());
		ProcessBean processBean = basicDataMapper.getProcessByWorkShopId(reportBean.getWorkShopName(),"交接出库");
		reportBean.setProcedur(processBean.getId());
		//判断车间生产单位是否足够多
		this.checkWorkShopIsEnough(reportBean);
		WarehouseInOutDetailBean widb=workshopService.reportToWarehouse(reportBean,dateString,4);
		reportBean.setOtherId(widb.getId());
		List<ReportBean> reportList=new ArrayList<ReportBean>();
		reportList.add(reportBean);
		List<WarehouseInOutDetailBean> warehouseList=new ArrayList<WarehouseInOutDetailBean>();
		warehouseList.add(widb);
		companyMaterialService.insertInOutRecode(warehouseList);//保存出入库记录
		workshopService.insertReport(reportList);
		String msg="";
		//需要过账审核
		if(isAduit) {
			Map<String,String> aduitMap=this.setAduitMap(map); 
			aduitMap.put("id", widb.getId());
			try {
				this.approvalWarehouse(aduitMap,1,request);
			} catch (CloneNotSupportedException e) {
				Assert.notNull(null,"审核时出现异常，请先退回，后审核");
			}
		}else {  
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String bodyMessage = "有车间多余物料退回入库单需审核";
			String queryCondition = "?ids="+widb.getId();
			 msg = companyMaterialService.sendWechatMessage("入库单待审核", 2, bodyMessage, sdf.format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 1);
		}
		return msg;
	}



    /**
     * 校验车间是否可退回
     * @param reportBean
     * @param dateString 
     */
	private void checkWorkShopIsEnough(ReportBean reportBean) {
		MergeBean mergeBean=workshopService.getMergeBean(reportBean.getWorkShopName());
		if(null != mergeBean) {
			Assert.notNull(null,mergeBean.getMergeWorkshop()+"已合并到"+mergeBean.getMergeToWorkShop()+"车间,请选择"+mergeBean.getMergeToWorkShop()+"车间交接");
		}
		//车间库存数
		long workShopStockCount=workshopService.getOrderTurnoverCount(reportBean);
		if(workShopStockCount<reportBean.getQualified()) {
			WorkshopProductionCycleBean wc=basicDataService.getWCById(reportBean.getWorkShopName());
			Assert.notNull(null,"订单编号："+reportBean.getOrderId()+",物料类型："+reportBean.getMachining()+",行号："+reportBean.getRowIndex()+"在"+wc.getWorkshopName()+"车间出库数不可超过库存："+workShopStockCount);
		}
	}



    /**
     * 批量退回多余物料
     * @param map
     * @param request 
     * @return
     */
	public String workShopSurplusMaterialReturnToWarehouseAll(Map<String, String> map, HttpServletRequest request) {
		StringUtil.checkIsTrue(map, "jsonArray", "未获取到参数");
		String josnStr=map.get("jsonArray");
		JSONArray jsonArray=JSONArray.fromObject(josnStr);
		List<ReportBean> list=(List<ReportBean>) JSONArray.toCollection(jsonArray, ReportBean.class);
		SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		String dateString=simpleDateFormat.format(new Date());
		simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
		String dayString=simpleDateFormat.format(new Date());
		Boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		for(ReportBean reportBean:list) {
			String returnStr=this.workShopSurplusMaterialReturnToWarehouse(reportBean,map,dateString,dayString,isAduit,request);
		}
		return ReturnStringUtil.SAVE_SUCCESS;
	}

	/**
	 *  从仓库直接发外协
	 *  metailArray
	 *  仓库出库所需数据
	    sourceType": 1
		warehouseType": 4,
		type": 2, 仓库出入库类型
		source": 2,
		feedOrder
		orderId
		rowIndex
		materialCode
		materialName
		materialType
		providerName
		model
		color
		remark
		count
		isProductionUnit
		selfOutFuCount
		
		
		//外协参数
		technology 工艺
		flowCycle 流程周期
		valuationUint 计价单位
		supplierId 供应商id
		supplierName 供应商名称
		unitPrice 外协单价
		valuationCount 计价数量
		type 外协类型
		maching 物料类型
	 *  additionalMaterialType 附加物料类型
	 *  additionalRowIndex 附加行号
	 * @throws CloneNotSupportedException 
	 */
	public String savePutOutFromWarehouse(Map<String, String> map,HttpServletRequest request,HttpServletResponse response) throws CloneNotSupportedException {
		map.put("isAduit", "true");
		//保存出入库记录  metailArray
		this.saveWarehouseOut(map,request);
		//生成外协单  传参  putoutOrderArray 
//		map.put("putoutOrderArray", map.get("metailArray"));
		Map newMap =RequestUtil.getRequestAllParam(request);
		newMap.put("request", request);
		newMap.put("isAduit", "true");
		putOutServiceNew.addPutoutOrder(newMap);
		return ReturnStringUtil.OPERATION_SUCCESS;
	}




	/**
	 ***********成品出库所需参数**************
	 * @param orderId(实际出库订单编号)
	 * @param type(类型 1 本订单  2 库存单)
	 * @param otherOrderId(其他订单编号  当类型不为1的时候有)
	 * @param rowIndexs(行号)
	 * @param remark(备注)
	 * @param outCount(出库数)
	 * @param customerName(客户名称)
	 * @param inOutUnit(出库单位 )
	 * @param inCountPrice(出库单价) 0 
	 * @param materialCode
	 * 
	 * ********添加物料的所有参数*****
	 * 
	 * @param map
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception 
	 */
	public String finishedProductToMaterial(Map<String, String> map,HttpServletRequest request) throws Exception {
		StringUtil.checkNotNull(map, "materialName", "未获取到物料名称");
		StringUtil.checkNotNull(map, "model", "未获取到物料规格");
		StringUtil.checkNotNull(map, "providerName", "未获取到供应商名称");
		StringUtil.checkNotNull(map, "materialCode", "未获取到物料代码");
		StringUtil.checkNotNull(map, "outCount", "未获取到物料代码");
		map.put("ralationWarehouse", "4");//转到原材料仓
		map.put("sourceType", "6");//是物料转仓
		map.put("inOutType", "12");
		MyUser myUser=RequestUtil.getLoginUser(request);
		CompanyMaterialTableBean companyMaterialTableBean=(CompanyMaterialTableBean) shoppingMallService.mapToObject(map, CompanyMaterialTableBean.class);
		//判断有无物料
		String materialCode=map.get("materialCode");
		//如果没有物料代码，先添加物料
		if("".equals(materialCode)) {
			List<CompanyMaterialTableBean> materialList=basicDataService.insertCompanyMaterial(companyMaterialTableBean,myUser);
			materialCode=materialList.get(0).getMaterialCode();
			map.put("materialCode", materialCode);
		}
		//生成成品出库记录，在此处调用成品出库销售方法
		String mString=otherWarehouseService.finishStockOut(map, request);
		return ReturnStringUtil.SAVE_SUCCESS+mString;
	}




	/**
	 * 无订单物料退回车间
	 * @param map
	 * @param request 
	 * @throws CloneNotSupportedException 
	 */
	public String  noOrderReturnToWarehouse(Map map, HttpServletRequest request) throws CloneNotSupportedException {
		StringUtil.checkIsTrue(map, "array", "");
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		String time=sdf.format(new Date());
		String metailArray=map.get("array").toString();
		JSONArray jsonArray=JSONArray.fromObject(metailArray);
		//前台传过来的物料集合
		List<CompanyMaterialTableBean> listCmtb=(List<CompanyMaterialTableBean>) JSONArray.toCollection(jsonArray, CompanyMaterialTableBean.class);
		//保存的出入库记录
		List<WarehouseInOutDetailBean> inOutList=new ArrayList<WarehouseInOutDetailBean>();
		//发送消息用的集合
		Map<String,Object> materialParam = new HashMap<String,Object>(); 
		materialParam.put("loginCompany", map.get("loginCompany"));
		List<String> idList = new ArrayList<String>();
		//是否是过账审核
		boolean isAduit=Boolean.parseBoolean(map.get("isAduit")==null?"fasle":map.get("isAduit").toString());
		Map<String,String> aduitMap=this.setAduitMap(map);
		for(CompanyMaterialTableBean cmtb:listCmtb) {
			materialParam.put("materialCode",cmtb.getMaterialCode());
	    	CompanyMaterialTableBean companyMaterialTableBean = companyMaterialMapper.getCompanyMaterialTableByMaterialCode(materialParam);
	    	Double canReturnCount=companyMaterialMapper.getNoOrderCanReturnCount(cmtb.getMaterialCode(),cmtb.getWorkShopId());
	    	Assert.isTrue(canReturnCount>=cmtb.getCount(),cmtb.getMaterialName()+"最多可退回"+canReturnCount);	    	
	    	this.isCheckMateiral(companyMaterialTableBean,"无法入库");
    		Assert.isTrue(cmtb.getCount().doubleValue()!=0, "入库数量为0");
    		Double count = cmtb.getCount();
		    WarehouseInOutDetailBean warehouseInOutDetailBean=new WarehouseInOutDetailBean();
		    warehouseInOutDetailBean.setCount(count);//入库数量
		    warehouseInOutDetailBean.setCreateTime(time);//入库时间
		    warehouseInOutDetailBean.setCreateUser(map.get("loginUserId").toString());
		    String rkId = dingTalkMapper.getApprovalNo("RK");
		    warehouseInOutDetailBean.setId(rkId);
		    warehouseInOutDetailBean.setMaterialCode(cmtb.getMaterialCode());//物料代码
		    warehouseInOutDetailBean.setPurcharseOrderId("车间退回物料");//入库投料单采购单对应表Id
		    warehouseInOutDetailBean.setType(4);
		    warehouseInOutDetailBean.setMaterialName(cmtb.getMaterialName());
		    warehouseInOutDetailBean.setColor(cmtb.getColor());
		    warehouseInOutDetailBean.setModel(cmtb.getModel());
		    warehouseInOutDetailBean.setProviderName(cmtb.getProviderName());
		    warehouseInOutDetailBean.setRemark(cmtb.getRemark());
		    warehouseInOutDetailBean.setWarehouseType(cmtb.getWarehouseType());
	    	warehouseInOutDetailBean.setStatus(0); 
		    warehouseInOutDetailBean.setInOutUnit(companyMaterialTableBean.getUnit());		    //入库单位
		    warehouseInOutDetailBean.setWarehouseInType(4);//采购入库类型 1订单采购入库 2库存采购入库 无采购单入库
		    warehouseInOutDetailBean.setCompany(map.get("loginCompany").toString());
		    warehouseInOutDetailBean.setWorkShopId(cmtb.getWorkShopId());
		    warehouseInOutDetailBean.setSource(4);//车间无订单发料
		    inOutList.add(warehouseInOutDetailBean);
		    idList.add(warehouseInOutDetailBean.getId());
	    	//插入入库记录 
		    if(inOutList !=null && inOutList.size()>0) {
		    	this.checkTakingIsNotApproval(inOutList, map.get("loginCompany").toString());
		    	companyMaterialMapper.insertInOutRecode(inOutList);
		    	if(isAduit) {
					aduitMap.put("id", inOutList.get(0).getId());
					this.approvalWarehouse(aduitMap,1,request);
				}
		    	inOutList.clear();
		    }
	    } 
		String mString="";
		 if(!isAduit){
			 String queryCondition = "?ids="+idList.toString().substring(1,idList.toString().length()-1).replace(" ","");
			 mString=companyMaterialService.sendWechatMessage("车间退库单", 2, "车间退库单待审批通知", sdf.format(new Date()), map, RedirectUrlUtil.queryWarehouse+queryCondition, 1);
		 }
		return ReturnStringUtil.RETURN_SUCCESS;
	}




	/**
	 * 获取仓库超出库存的部分
	 * @param map
	 * @return
	 */
	public List<CompanyMaterialTableBean> warehouseBeyondMax(Map map) {
		return warehouseMapper.warehouseBeyondMax(map);
	}




	/**
	 * 获取超出库存下限的物料
	 * @param map
	 * @return
	 */
	public List<CompanyMaterialTableBean> warehouseBeyondMin(Map map) {
		return warehouseMapper.warehouseBeyondMin(map);
	}




	/**
	 * 获取呆滞物料
	 * @param map
	 * @return
	 */
	public List<CompanyMaterialTableBean> getStillnessMaterial(Map map) {
		return warehouseMapper.getStillnessMaterial(map);
	}




	/**
	 * 获取收款拖期数据
	 * @param map
	 * @return
	 */
	public List<WarehouseInOutDetailBean> getReceivablesDelayData(Map map) {
		return warehouseMapper.getReceivablesDelayData(map);
	}
	
}
